الفرق بين المراجعتين لصفحة: «Arduino/volatile»
جميل-بيلوني (نقاش | مساهمات) أنشأ الصفحة ب'تصنَّف الكلمة volatile المفتاحية من «مقيدات المتغيرات» (variable qualifier)، وتُستعمَل عادةً قبل نوع الم...' |
جميل-بيلوني (نقاش | مساهمات) لا ملخص تعديل |
||
سطر 1: | سطر 1: | ||
تصنَّف الكلمة volatile المفتاحية | تصنَّف الكلمة <code>volatile</code> المفتاحية ضمن «مقيدات المتغيرات» (variable qualifier)، وتُستعمَل عادةً قبل نوع المتغير عند تعريفه لتعديل الطريقة التي يعامل فيها المصرِّف والبرنامج اللاحق هذا المتغير. | ||
تمثِّل الكلمة volatile المفتاحية عند استعمالها في تعريف متغير توجيهًا (directive) للمصرِّف نفسه. المصرِّف هو برنامج وظيفته تحويل الشيفرة المكتوبة بلغة ++C/C إلى شيفرة تنفيذية يفهمها العتاد؛ تحوي هذه الشيفرة التنفيذية | تمثِّل الكلمة <code>volatile</code> المفتاحية عند استعمالها في تعريف متغير توجيهًا (directive) للمصرِّف نفسه. المصرِّف هو برنامج وظيفته تحويل الشيفرة المكتوبة بلغة ++C/C إلى شيفرة تنفيذية يفهمها العتاد؛ تحوي هذه الشيفرة التنفيذية أوامر فعلية للمتحكم الموجود على لوحة أردوينو تخبره بما يتوجب عليه فعله. | ||
الأمر الذي تفعله الكلمة <code>volatile</code> المفتاحية مع المتغير هو توجيه المصرِّف إلى تحميل المتغير من الذاكرة RAM وليس من سجلات التخزين للذاكرة المؤقتة (الذاكرة flash) حيث تُخزَّن جميع متغيرات البرنامج. في بعض الحالات، القيمة المخزَّنة في المسجلات لمتغيرٍ ما قد تكون غير دقيقة. | الأمر الذي تفعله الكلمة <code>volatile</code> المفتاحية مع المتغير هو توجيه المصرِّف إلى تحميل المتغير من الذاكرة RAM وليس من سجلات التخزين للذاكرة المؤقتة (الذاكرة flash) حيث تُخزَّن جميع متغيرات البرنامج. في بعض الحالات، القيمة المخزَّنة في المسجلات لمتغيرٍ ما قد تكون غير دقيقة. | ||
يجب أن يعرَّف المتغير مع الكلمة volatile المفتاحية متى ما كان بالإمكان تغيير قيمته عبر شيء يتجاوز تحكم جزء الشيفرة الذي يظهر هذا المتغير ضمنه، مثل تنفيذ خيط في وقت واحد. في أردوينو، المكان الوحيد الذي يحتمل أن يحدث فيه هذا الأمر هو أجزاء الشيفرة المرتبطة بالمقاطعات والتي تدعى ببرامج خدمة المقاطعة الفرعية (ISR). | يجب أن يعرَّف المتغير مع الكلمة <code>volatile</code> المفتاحية متى ما كان بالإمكان تغيير قيمته عبر شيء يتجاوز تحكم جزء الشيفرة الذي يظهر هذا المتغير ضمنه، مثل تنفيذ خيط في وقت واحد. في أردوينو، المكان الوحيد الذي يحتمل أن يحدث فيه هذا الأمر هو أجزاء الشيفرة المرتبطة [[Arduino/interrupts|بالمقاطعات]] والتي تدعى [[Arduino/interrupts/attachinterrupt|ببرامج خدمة المقاطعة الفرعية]] (ISR). | ||
== الأعداد الصحيحة المتطايرة أم | == الأعداد الصحيحة المتطايرة أم الطويلة المتطايرة؟ == | ||
إن استعملت الكلمة volatile مع متغير يزيد حجمه عن بايت واحد (2 بايت مثل العدد | إن استعملت الكلمة <code>volatile</code> مع متغير يزيد حجمه عن بايت واحد (2 بايت مثل [[Arduino/int|العدد الصحيح]]، أو 4 بايت مثل [[Arduino/long|العدد الطويل]] ...إلخ.)، فلن يتمكن المتحكم من قراءته في خطوة واحدة لأنَّ معمارية المتحكم هي 8 بت غالبًا (تأكد من معمارية المتحكم في لوحتك). هذا يعني أنَّه بينما يقرأ جزء الشيفرة (مثل الجزء <code>[[Arduino/loop|()loop]]</code>) أول ثمانية بتات من المتغير، قد تكون المقاطعة قد غيِّرت مسبقًا البتات الثمانية الأخرى (في حال كان حجم المتغير 16 بت). سيؤدي هذا إلى الحصول على قيمة عشوائية للمتغير. | ||
حلُّ هذه المشكلة هو تعطيل المقاطعات أثناء قراءة قيم المتغيرات، وبذلك لا تتغير | حلُّ هذه المشكلة هو تعطيل المقاطعات أثناء قراءة قيم المتغيرات، وبذلك لا تتغير قيم بتات المتغير أثناء قراءتها. توجد عدة طرق لفعل ذلك منها: | ||
* استعمال الدالة | * استعمال الدالة <code>[[Arduino/interrupts/nointerrupts|()noInterrupts]]</code> لتعطيل المقاطعات، أو | ||
* استعمال | * استعمال الكتلة <code>[https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html ATOMIC_BLOCK]</code>، إذ العمليات الذرية (atomic operations) هي عمليات مفردة يجريها المتحكم (MCU) وتمثِّل أصغر وحدة محتملة. | ||
== أمثلة == | == أمثلة == |
مراجعة 13:35، 27 أكتوبر 2018
تصنَّف الكلمة volatile
المفتاحية ضمن «مقيدات المتغيرات» (variable qualifier)، وتُستعمَل عادةً قبل نوع المتغير عند تعريفه لتعديل الطريقة التي يعامل فيها المصرِّف والبرنامج اللاحق هذا المتغير.
تمثِّل الكلمة volatile
المفتاحية عند استعمالها في تعريف متغير توجيهًا (directive) للمصرِّف نفسه. المصرِّف هو برنامج وظيفته تحويل الشيفرة المكتوبة بلغة ++C/C إلى شيفرة تنفيذية يفهمها العتاد؛ تحوي هذه الشيفرة التنفيذية أوامر فعلية للمتحكم الموجود على لوحة أردوينو تخبره بما يتوجب عليه فعله.
الأمر الذي تفعله الكلمة volatile
المفتاحية مع المتغير هو توجيه المصرِّف إلى تحميل المتغير من الذاكرة RAM وليس من سجلات التخزين للذاكرة المؤقتة (الذاكرة flash) حيث تُخزَّن جميع متغيرات البرنامج. في بعض الحالات، القيمة المخزَّنة في المسجلات لمتغيرٍ ما قد تكون غير دقيقة.
يجب أن يعرَّف المتغير مع الكلمة volatile
المفتاحية متى ما كان بالإمكان تغيير قيمته عبر شيء يتجاوز تحكم جزء الشيفرة الذي يظهر هذا المتغير ضمنه، مثل تنفيذ خيط في وقت واحد. في أردوينو، المكان الوحيد الذي يحتمل أن يحدث فيه هذا الأمر هو أجزاء الشيفرة المرتبطة بالمقاطعات والتي تدعى ببرامج خدمة المقاطعة الفرعية (ISR).
الأعداد الصحيحة المتطايرة أم الطويلة المتطايرة؟
إن استعملت الكلمة volatile
مع متغير يزيد حجمه عن بايت واحد (2 بايت مثل العدد الصحيح، أو 4 بايت مثل العدد الطويل ...إلخ.)، فلن يتمكن المتحكم من قراءته في خطوة واحدة لأنَّ معمارية المتحكم هي 8 بت غالبًا (تأكد من معمارية المتحكم في لوحتك). هذا يعني أنَّه بينما يقرأ جزء الشيفرة (مثل الجزء ()loop
) أول ثمانية بتات من المتغير، قد تكون المقاطعة قد غيِّرت مسبقًا البتات الثمانية الأخرى (في حال كان حجم المتغير 16 بت). سيؤدي هذا إلى الحصول على قيمة عشوائية للمتغير.
حلُّ هذه المشكلة هو تعطيل المقاطعات أثناء قراءة قيم المتغيرات، وبذلك لا تتغير قيم بتات المتغير أثناء قراءتها. توجد عدة طرق لفعل ذلك منها:
- استعمال الدالة
()noInterrupts
لتعطيل المقاطعات، أو - استعمال الكتلة
ATOMIC_BLOCK
، إذ العمليات الذرية (atomic operations) هي عمليات مفردة يجريها المتحكم (MCU) وتمثِّل أصغر وحدة محتملة.
أمثلة
تبديل حالة رجل متصلة مع ضوء ليد عند حدوث مقاطعة على الرجل 2:
int pin = 13;
volatile byte state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state;
}