الدالة attachInterrupt()‎ في أردوينو

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

تفعِّل الدالة attachInterrupt()‎ مقاطعة خارجية معيَّنة على إحدى الأرجل في لوحة أردينو. المعامل الأول المُمرَّر إليها هو رقم المقاطعة. عمومًا، يجب استدعاء الدالة digitalPinToInterrupt(pin)‎ لتفسير الرجل الرقمية الفعلية إلى رقم مقاطعة محدَّدة. على سبيل المثال، إن أردت تهيئة مقاطعة على الرجل 3، فاستعمل digitalPinToInterrupt(3)‎ بتمريرها كأول معامل إلى الدالة attachInterrupt()‎.

اللوحة الأرجل الرقمية القابلة للاستخدام مع المقاطعات
Uno, Nano, Mini, other 328-based 2، 3
Uno WiFi Rev.2 جميع الأرجل الرقمية
Mega, Mega2560, MegaADK 2، 3، 18، 19، 20، 21
Micro, Leonardo, other 32u4-based 0، 1، 2، 3، 7
Zero جميع الأرجل الرقمية باستثناء الرجل 4
لوحات عائلة MKR 0، 1، 4، 5، 6، 7، 8، 9، A2 ،A1
Due جميع الأرجل الرقمية
101 جميع الأرجل الرقمية (الأرجل 2، و 5، و 7، و 8، و 10، و 12، و 13 تعمل مع الوضع CHANGE فقط)

فائدة استعمال المقاطعات

تمكن فائدة المقاطعات بتوفيرها طريقةً لتنفيذ شيء أو جعل شيء يحدث تلقائيًّا أثناء تنفيذ برنامج، بالإضافة إلى توفيرها حلولًا للمشاكل المتعلقة بالتوقيت. من الأمثلة الجيدة التي تستخدم المقاطعات هي قراءة مرمِّز دوار (rotary encoder)، أو مراقبة المدخلات من المستخدم.

إن أردت إنشاء برنامج يلتقط النبضات من مرمِّز دوار بشكل دائم ولا يفقد أية نبضة واحدة مطلقًا، فمن الصعب أن ينفّذ هذا البرنامج أي شيء آخر لأنَّه سيحتاج إلى التنصت على أرجل الحساس للمرمز باستمرار ريثما يلتقط النبضات عند حدوثها. تملك بعض الحساسات واجهة ديناميكية مشابهة أيضًا مثل محاول قراءة حساس صوت من أجل التقاط صوت نقرة أو ضغطة معيَّنة، أو محاولة التقاط حساس أشعة تحت الحمراء (infrared) -مثل قاطع ضوئي (photo-interrupter)- سقوط قطعة معدنية لبدء تنفيذ أمر أو مهمة ما. باستعمال المقاطعات مع جميع هذه الأمثلة وغيرها، يمكن جعل المتحكم حرًّا في تنفيذ مهام وأعمال أخرى دون إهمال تنفيذ مهام معيَّنة مرتبطة بوقوع أحداث خارجية في أي لحظة مثل تلك التي أشرنا إليها آنفًا.

برنامج خدمة المقاطعة (Interrupt Service Routines)

برامج خدمة المقاطعة الفرعية (تدعى اختصارًا ISR) هي نوع مخصَّص من الدوال التي تملك بعض القيود الفريدة الغير موجودة في الدوال الأخرى. فلا يمكن مثلًا تمرير أيَّة معاملات إلى تلك الدوال ولا يجب أن تعيد أي شيء.

عمومًا، يجب على برنامج خدمة المقاطعة أن يكون قصيرًا وسريعًا قدر الإمكان. إن كانت تملك شيفرتك عدة برامج خدمة المقاطعات، فيجب أن تعمل إحداها فقط في وقت واحد بينما ستُنفَّذ مقاطعات أخرى واحدةً تلو الأخرى، في حال حدوث أكثر من مقاطعة في الوقت نفسه، بترتيب يعتمد على أولوية كلٍّ منها. تعتمد الدالة millis()‎ على المقاطعات لعد الزمن، لذا لن تعمل أو تزيد داخل برنامج خدمة مقاطعة. لمَّا كان عمل الدالة delay()‎ يتطلب المقاطعات أيضًا، فلن تعمل إن استدعيت ضمن برنامج خدمة مقاطعة. أمَّا الدالة delay()‎، فإنَّها تعمل بالبداية بشكل جيد ولكن سلوكها يبدأ بالتدهور تدريجيًّا بعد مرور 1-2 ميلي ثانية. لا تستعمل الدالة delayMicroseconds()‎ العداد (counter) في المتحكم، لذا ستعمل بشكل طبيعي ضمن برنامج خدمة المقاطعة.

تُستخدَم عادةً المتغيرات العامة (global variables) لتمرير البيانات بين برنامج خدمة المقاطعة الفرعي والبرنامج الرئيسي. لتكون متيقِّنًا تمامًا من استعمال المتغيرات المشتركة بين خدمة المقاطعة والبرنامج الرئيسي بشكل صحيح وتحديثها للبيانات دون حصول خطأ، استعمل الكلمة volatile المفتاحية للتصريح عن تلك المتغيرات.

للمزيد من المعلومات حول المقاطعات، اطلع على هذه الملاحظات.

البنية العامة

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); (يوصى بها)
attachInterrupt(interrupt, ISR, mode); (لا يوصى بها)
attachInterrupt(pin, ISR, mode); (101 و ،MKR1000 و ،Zero و ،Due لا يوصى بها؛ خاصة بلوحات)

المعاملات

interrupt

عددٌ صحيحٌ يمثِّل رقم المقاطعة.

pin

رقم الرجل التي يراد تفعيل المقاطعة عليها ،ويُستعمَل غالبًا مع digitalPinToInterrupt()‎ (يستعمل مباشرةً مع لوحات Due، و Zero، و MKR1000 فقط).

ISR

دالةٌ تمثِّل برنامج خدمة المقاطعة (ISR) المراد استدعاؤه وتنفيذه عند وقوع المقاطعة. يجب على هذه الدالة أن لا تأخذ أي معامل ولا تعيد أي شيء.

mode

يحدِّد متى يجب على المقاطعة أن تُستدعَى (triggered). توجد أربعة ثوابت معرَّفة مسبقًا يمكن استعمالها مع هذا المعامل:

  • LOW: تُستدعَى المقاطعة متى ما أصبحت حالة الرجل منخفضة (low).
  • CHANGE: تُستدعَى المقاطعة متى ما تغيِّرت حالة الرجل (من مرتفعة إلى منخفضة أو العكس).
  • RISING: تُستدعَى المقاطعة متى ما انتقلت حالة الرجل من الحالة المنخفضة (low) إلى الحالة المرتفعة (High).
  • FALLING: تُستدعَى المقاطعة متى ما انتقلت حالة الرجل من الحالة المرتفعة (High) إلى الحالة المنخفضة (low).

يمكن استعمال الثابت الإضافي التالي أيضًا مع اللوحات Due، و Zero ، و MKR1000:

  • HIGH: تُستدعَى المقاطعة متى ما أصبحت حالة الرجل مرتفعة (High).

القيم المعادة

لا يعاد أي شيء.

أمثلة

مثال على قلب حالة رجل متصلة بضوء ليد كلما حصلت مقاطعة خارجية عبر تغيِّر حالة الرجل 2:

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

أرقام المقاطعات

يجب عمومًا استعمال digitalPinToInterrupt(pin)‎ عوضًا عن كتابة رقم المقاطعة مباشرةً في الدالة attachInterrupt()‎. تختلف الأرجل المخصَّصة للمقاطعات وتحويلها إلى رقم مقاطعة من نوع لوحة إلى أخرى. قد يبدو للوهلة الأولى أن استعمال أعداد المقاطعات أسهل وأبسط ولكن يمكن أن يُسبِّب مشكلةً في التوافقية عندما يعمل برنامجك على لوحة أخرى مختلفة.

على أي حال، تملك الشيفرات القديمة غالبًا أعداد مقاطعات مباشرة، إذ استُعمِل العدد 0 من أجل الرجل 2 الرقمية، والعدد 1 من أجل الرجل 3 الرقمية أحيانًا كثيرة. يوضِّح الجدول الآتي الأرجل التي تتوافر فيها خاصية المقاطعة في مختلف اللوحات.

انتبه إلى أنَّ أعداد المقاطعات في الجدول الآتي تشير إلى العدد الذي يجب يمرَّر إلى الدالة attachInterrupt()‎. لأسباب تاريخية، لا تتطابق عملية الترقيم الموضحة في الجدول مع عملية ترقيم المقاطعات في شريحة متحكمات ATmega (مثل int.0 تتطابق مع INT4 في شريحة ATmega2560).

اللوحة INT.0 INT.1 INT.2 INT.3 INT.4 INT.5
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
اللوحات التي تستند على المتحكمات التي من النوع 32u4 (مثل Leonardo، و Micro) 3 2 0 1 7

أمَّا في لوحات التي من عائلة Uno WiFiRev.2، و Due، و Zero، و MKR، و 101، فيكون رقم المقاطعة فيها مساويًا إلى رقم الرجل.

ملاحظات وتحذيرات

ضمن الدالة ISR المرتبطة، لن تعمل الدالة delay()‎، ولن تزيد القيمة المعادة عبر الدالة millis()‎. البيانات المستلمة عبر الاتصال التسلسلي في فترة تنفيذ الدالة قد تُفقَد. يجب عليك التصريح عن أيَّ متغير تود تعديله ضمن الدالة ISR المرتبطة بمقاطعة بالكلمة volatile المفتاحية. اطلع على القسم «برنامج خدمة المقاطعة» في الأعلى لمزيد من التوضيح.

انظر أيضًا

  • الدالة detachInterrupt()‎: تعطِّل عمل مقاطعة خارجية معيَّنة مرتبطة بإحدى أرجل اللوحة.
  • الدالة interrupts()‎: تعيد تفعيل عمل المقاطعات بعد إيقافها عبر استدعاء الدالة nointerrupts()‎.
  • الدالة noInterrupts()‎: تعطِّل عمل جميع المقاطعات في لوحة أردوينو.

مصادر