المشاركة باستخدام volatile
جزء من قسم التوقيت دون delay في رحلة Arduino على Coddy. الدرس 14 من 18.
ينبغي لمُعالج المقاطعة (ISR) أن ينفّذ أمرًا سريعًا واحدًا، لذا فهو عادةً يضبط متغيرًا ليقرأه باقي البرنامج. يجب التصريح عن المتغير الذي يستخدمه كلاهما باستخدام volatile:
volatile bool started = false;
void onPress() {
started = true;
}لتوفير الوقت، قد يحتفظ المُصرّف (البرنامج الذي يحوّل C++ إلى تعليمات الشريحة) بنسخة من متغير داخل المعالج بدلًا من قراءة الذاكرة. فهو لا يعرف أن مقاطعةً ما قد تغيّر المتغير، لذا قد يستمر البرنامج في استخدام النسخة القديمة إلى الأبد. تجعل volatile البرنامج يقرأ المتغير من جديد في كل مرة.
ينتظر هذا البرنامج في setup() باستخدام حلقة while: تكرّر while (condition) { } ما بين القوسين المعقوفين ما دام الشرط صحيحًا، والشرط هنا هو !started. وكما في قسم المدخلات، تعني ! «ليس»: تتكرر الحلقة ما دام started غير صحيح. من دون volatile، قد ينتظر البرنامج إلى الأبد، حتى بعد الضغط.
التحدي
سهليجب أن ينتظر هذا البرنامج حتى يُضغط على الزر، ثم يومض مؤشر LED. لكنه الآن ينتظر إلى الأبد. أصلح ذلك:
- في
onPress()، عيّنstartedإلىtrue - صرّح عن
startedباستخدامvolatile
اضغط على Run، ثم اضغط على الزر، وبعد ذلك اضغط على Check. جرّب ذلك مرة واحدة دون volatile لترى اللوحة وهي عالقة.
جرّب بنفسك
const int ledPin = 13;
const int buttonPin = 2;
bool started = false; // يُضبط بواسطة المقاطعة ويقرأه البرنامج
unsigned long previousMillis = 0;
int ledState = LOW;
void onPress() {
// اضبط started على true هنا
}
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);
// انتظر هنا حتى يُضغط الزر
while (!started) {
}
}
void loop() {
// أومض كل 250 ms
unsigned long now = millis();
if (now - previousMillis >= 250) {
previousMillis = now;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس التوقيت دون delay
تدرّب بنفسك: Playground لـ Arduino