 |
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
|
|
نشاط [ F.Abdelaziz ]
قوة السمعة:332
|
|
22-02-2020, 05:43 PM
المشاركة 1
|
|
مقاطعات الاردوينو Arduino Interrupts
مفهوم المقاطعة :
إعتبر سيارة سريعة الحركة ، إذا صدمت سيارة أخرى فجأة في الاتجاه المعاكس ، فإن أول شيء يحدث هو أن مستشعر التسارع accelerometer الموجود في السيارة يستشعر حدوث عدم تسارع de-acceleration (تباطؤ) مفاجئ ويؤدي إلى مقاطعة خارجية للميكروكونترولر (المتحكم الدقيق) الموجود في السيارة ، ثم ينتج المتحكم إشارة كهربائية لنشر الأكياس الهوائية على الفور. يقوم المتحكم الموجود في السيارة بمراقبة العديد من الأشياء في وقت واحد مثل استشعار سرعة السيارة ، والتحقق من أجهزة الاستشعار الأخرى ، والتحكم في درجة حرارة مكيف الهواء وما إلى ذلك. فما الذي يجعل الفتح المفاجىء لكيس الهواء في ثوانٍ؟ يتم استخدام إشارة المقاطعة Interrupt هنا والتي لها الأولوية القصوى للجميع.
مثال بسيط آخر على المقاطات Interrupts هو الهواتف المحمولة التي تعمل باللمس والتي لها الأولوية القصوى للإحساس باللمس "Touch". لدى كل جهاز إلكتروني تقريبًا نوع من المقاطعات لإيقاف (مقاطعة) العملية المعتادة والقيام ببعض الأشياء ذات الأولوية العليا عند حدث معين. يتم استئناف العملية العادية بعد قضاء المقاطعة.
من الناحية الفنية ، تعد المقاطعات Interrupts آلية يمكن بواسطتها تعليق (إيقاف) الإدخال / الإخراج أو التعليمة من التنفيذ العادي للمعالج والحصول على خدماته كما لوأن لها أولوية مرتفعة . على سبيل المثال ، يمكن مقاطعة المعالج الذي يقوم بتنفيذ عادي من قبل بعض أجهزة الاستشعار لتنفيذ عملية معينة موجودة في ISR (روتين خدمة المقاطعة). بعد تنفيذ المعالج ISR يمكن مرة أخرى استئناف التنفيذ العادي.
أنواع المقاطعات :
هناك نوعان من المقاطعات:
مقاطعة الأجهزة (الهاردوير) Hardware Interrupt : يحدث ذلك عندما يحدث حدث خارجي مثل تغيير حالة طرف المقاطعة الخارجي حالته من LOW إلى HIGH أو LIGH إلى LOW .
مقاطعة البرمجيات Software Interrupt : يحدث وفقا للتعليمات من البرمجيات . على سبيل المثال مقاطعات المؤقت Timer هي مقاطعة برمجية .
المقاطعات في الاردوينو :
الآن سوف نرى كيفية استخدام المقاطعات في لوحة الاردوينو ، والتى لها نوعان من المقاطعات:
• مقاطعة خارجية External Interrupt .
• مقاطعة تغيير الطرف Pin Change Interrupt.
المقاطعة الخارجية External Interrupt :
يتم تفسير هذه المقاطعة بواسطة الأجهزة hardware وتكون سريعة جداً. يمكن تعيين هذه المقاطعات ليتم تشغيلها في حالة حدوث مستويات "صاعدة " RISING أو "هابطة " FALLING أو الحالة LOW.
فى الاردوينو أونو UNO والنانو NANO تخصص الأطراف الرقمية 2 و 3 للمقاطعة الخارجية .
مقاطعات تغيير الطرف Pin Change Interrupts :
يمكن أن يكون للاردوينو أطراف مقاطعة أكثر تمكن enabled باستخدام المقاطعات Pin Change . في لوحات الاردوينو القائمة على المتحكمات ATmega168 / 328 ، يمكن استخدام أي الأطراف أو جميع أطراف الإشارة العشرين كأطراف مقاطعة. يمكن أيضًا تشغيلها باستخدام الحواف الصاعدة RISING أو الهابطة FALLING .
استخدام المقاطعات الخارجية في الاردوينو :
من أجل استخدام المقاطعات في الاردوينو ، يجب فهم المفاهيم التالية.
روتين خدمة المقاطعة Interrupt Service Routine (ISR) :
روتين خدمة المقاطعة ISR أو معالج المقاطعة Interrupt handler هو حدث يحتوي على مجموعة صغيرة من التعليمات . عند حدوث مقاطعة خارجية ، يقوم المعالج أولاً بتنفيذ هذه التعليمات البرمجية الموجودة في ISR ويعود مرة أخرى إلى الحالة التي ترك فيها التنفيذ العادي.
بناء جملة ISR فى الاردوينو كما يلى :
كود:
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);
الوسيط الأول :
كود:
digitalPinToInterrupt(pin)
في الاردوينو أونو Uno ، ونانو NANO الأطراف المستخدمة للمقاطعة هي 2,3 وفى الميجا mega هى 2,3,18,19,20,21 . يتم تحديد طرف الدخل المستخدم للمقاطعة الخارجية هنا.
الوسيط الثانى :
ISR: هي دالة تستدعى عند إجراء مقاطعة خارجية.
الوسيط الثالث :
Mode : نوع الانتقال إلى التشغيل trigger ، على سبيل المثال falling ، rising ، إلخ.
• RISING : لتشغيل مقاطعة عندما ينتقل طرف من LOW إلى HIGH.
• FALLING : لتشغيل مقاطعة عندما ينتقل طرف من HIGH إلى LOW .
• CHANGE : لتشغيل المقاطعة عندما ينتقل طرف من LOW إلى HIGH أو من HIGH إلى LOW (أي عندما تتغير حالة الطرف ).
بعض الشروط أثناء استخدام المقاطعة :
• روتين خدمة مقاطعة المقاطعة (ISR) يجب أن يكون أقصر ما يمكن.
• الدالة Delay () لا تعمل داخل ISR ويجب تجنبها.
في هذا التدريب الخاص بمقاطعة الاردوينو ، يتم زيادة عدد number من 0 (العمل العادى) ويتم استخدام زري ضغط لتشغيل مقاطعة ، كل واحد متصل بطرف D2 & D3. يتم استخدام ليد LED لبيان المقاطعة. في حالة الضغط على زر الضغط الأول ، يتم تشغيل الليد ON ويظهر العرض interrupt2 ويختفى ، وعندما يتم الضغط على زر الضغط الثانى ، يتم إيقاف تشغيل الليد OFF ويظهر العرض interrupt1 ويختفى .
الدائرة الكهربية :

يتم توصيل اثنين من أزرار الضغط للاردوينو أونو في الأطراف D2 و D3. يتم استخدامها لعمل مقاطعتين خارجيتين ، أحدهما لتشغيل ليد LED والآخر لإيقاف تشغيل الليد LED. كل زر ضغط لديه مقاومة سحب لأسفل بقيمة 10k متصلة بالأرضى. لذلك عند الضغط على زر الضغط ، يكون المنطق HIGH (1) وعندما لا يتم الضغط عليه يكون المنطق LOW (0) . مقاومة السحب لأسفل إلزامية ، وإلا ستكون هناك قيم عائمة عند طرفى الدخل D2 & D3.
كما يتم استخدام ليد LED لبيان أن المقاطعة قد تم تشغيلها أو الضغط على زر.
برمجة مقاطعة الاردوينو :
في هذا التدريب ، يتم زيادة عدد من 0 والذي يتم عرضه بشكل مستمر على شاشة LCD (16x2) المتصلة مع الاردوينو أونو ، كلما تم الضغط على الزر الأيمن (طرف المقاطعة D3) ، يتم تشغيل الليد LED ويظهر العرض Interrupt2 ، وعند الضغط على الزر الأيسر (طرف المقاطعة D2) يتم إيقاف تشغيل الليد LED ويظهر العرض Interrupt1.
البرنامج :
كود:
//Interrupts using Arduino
//Circuit Digest
#include<LiquidCrystal.h> // Including lcd display library
LiquidCrystal lcd (7,8,9,10,11,12); // Define LCD display pins RS,E,D4,D5,D6,D7
volatile int output = LOW;
int i = 0;
void setup()
{
lcd.begin(16,2); // setting LCD as 16x2 type
lcd.setCursor(0,0);
lcd.print("CIRCUIT DIGEST");
lcd.setCursor(0,1);
lcd.print("ArduinoInterrupt");
delay(3000);
lcd.clear();
pinMode(13,OUTPUT);
attachInterrupt(digitalPinToInterrupt(2),buttonPressed1,RISING); // function for creating external interrupts at pin2 on Rising (LOW to HIGH)
attachInterrupt(digitalPinToInterrupt(3),buttonPressed2,RISING); // function for creating external interrupts at pin3 on Rising (LOW to HIGH)
}
void loop()
{
lcd.clear();
lcd.print("COUNTER:");
lcd.print(i);
++i;
delay(1000);
digitalWrite(13,output); //Turns LED ON or OFF depending upon output value
}
void buttonPressed1() //ISR function excutes when push button at pinD2 is pressed
{
output = LOW; //Change Output value to LOW
lcd.setCursor(0,1);
lcd.print("Interrupt 1");
}
void buttonPressed2() //ISR function excutes when push button at pinD3 is pressed
{
output = HIGH; //Change Output value to HIGH
lcd.setCursor(0,1);
lcd.print("Interrupt2");
}
الوصف :
1- فى البداية ً يتم تضمين ملف الرأس لشاشة LCD ومن ثم يتم تعريف أطراف LCD المستخدمة في الاتصال مع الاردوينو .أيضا يتم إعلان المتغيرات . لاحظ إلان المتغير output المستخدم بروتين خدمة المقاطعة باعتباره volatile .
كود:
#include<LiquidCrystal.h>
LiquidCrystal lcd (7,8,9,10,11,12); // Define LCD display pins RS, E, D4, D5, D6, D7
volatile int output = LOW;
int i = 0;
2- داخل الدالة setup ، يتم عرض بعد الرسائل الافتتاحية على شاشة LCD .
كود:
void setup()
{
lcd.begin(16,2); // setting LCD as 16x2 type
lcd.setCursor(0,0);
lcd.print("CIRCUIT DIGEST");
lcd.setCursor(0,1);
lcd.print("ArduinoInterrupt");
delay(3000);
lcd.clear();
pinMode(13,OUTPUT);
attachInterrupt(digitalPinToInterrupt(2),buttonPressed1,RISING); // function for creating external interrupts at pin2 on Rising (LOW to HIGH)
attachInterrupt(digitalPinToInterrupt(3),buttonPressed2,RISING); // function for creating external interrupts at pin3 on Rising (LOW to HIGH)
}
3- ثم في نفس الدالة setup يجب تحديد أطراف الدخل والخرج . يتم توصيل الطرف D13 بأنود الليد LED ، لذلك يجب تعريف هذا الطرف على أنه خرج .
4- الآن الجزء الرئيسي المهم في البرمجة هو الدالة attachInterrupt() ، ويتم تضمينها أيضا داخل الدالة setup .
كود:
attachInterrupt(digitalPinToInterrupt(2),buttonPressed1,RISING); // function for creating external interrupts at pin2 on Rising (LOW to HIGH)
attachInterrupt(digitalPinToInterrupt(3),buttonPressed2,RISING); // function for creating external interrupts at pin3 on Rising (LOW to HIGH)
هنا ، يتم تحديد أن الطرف 2 هو للمقاطعة الخارجية ، ويتم استدعاء الدالة buttonPressed1 عندما يكون هناك RISING (LOW to HIGH) عند D2. والطرف 3 هو أيضًا للمقاطعة الخارجية ويتم استدعاء الدالة buttonPressed2 عندما يكون هناك RISING على الطرف D3.
5- داخل الدالة loop ، يتم زيادة العدد (i) من الصفر وطباعته على شاشة LCD(16x2) .
كود:
void loop()
{
lcd.clear();
lcd.print("COUNTER:");
lcd.print(i);
++i;
delay(1000);
digitalWrite(13,output); //Turns LED ON or OFF depending upon output value
}
في نفس الدالة loop ، يتم استخدام الدالة digitalWrite على الطرف D13 حيث يتم توصيل أنود الليد LED. اعتمادًا على قيمة المتغير output، سيتم تشغيل الليد LED أو إيقاف تشغيله .
كود:
digitalWrite(13,output); //Turns LED ON or OFF depending upon output value
6- الجزء الأكثر أهمية هو إنشاء دالة معالج المقاطعة وفقًا للاسم المستخدم في الدالة attachInterrupt.
نظرا لأنه تم استخدام أطراف المقاطعة 2 و 3 لذلك مطلوب اثنين ISR كما يلى :
كود:
void buttonPressed1() //ISR function excutes when push button at pinD2 is pressed
{
output = LOW; //Change Output value to LOW
lcd.setCursor(0,1);
lcd.print("Interrupt 1");
}
يتم تنفيذ هذه الدالة عند الضغط على زر الضغط على الطرف D2 (RISING EDGE) . تعمل هذه الدالة على تغيير حالة الخرج إلى LOW مما يؤدي إلى إيقاف تشغيل الليد LED وطباعة “interrupt1” على شاشة LCD.
كود:
void buttonPressed2() //ISR function executes when push button at pinD3 is pressed
{
output = HIGH; //Change Output value to HIGH
lcd.setCursor(0,1);
lcd.print("Interrupt2");
}
يتم تنفيذ هذه الدالة عند الضغط على زر الضغط على الطرف D3. تعمل هذه الدالة على تغيير حالة output إلى HIGH مما يؤدي إلى تشغيل الليد LED وطباعة “interrupt2” على شاشة LCD.
|