الفرق بين المراجعتين لصفحة: «Arduino/volatile»
جميل-بيلوني (نقاش | مساهمات) لا ملخص تعديل |
جميل-بيلوني (نقاش | مساهمات) طلا ملخص تعديل |
||
(2 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:الكلمة <code>volatile</code> المفتاحية في أردوينو}}</noinclude> | |||
تصنَّف الكلمة <code>volatile</code> المفتاحية ضمن «مقيدات المتغيرات» (variable qualifier)، وتُستعمَل عادةً قبل نوع المتغير عند تعريفه لتعديل الطريقة التي يعامل فيها المصرِّف والبرنامج اللاحق هذا المتغير. | تصنَّف الكلمة <code>volatile</code> المفتاحية ضمن «مقيدات المتغيرات» (variable qualifier)، وتُستعمَل عادةً قبل نوع المتغير عند تعريفه لتعديل الطريقة التي يعامل فيها المصرِّف والبرنامج اللاحق هذا المتغير. | ||
سطر 5: | سطر 6: | ||
الأمر الذي تفعله الكلمة <code>volatile</code> المفتاحية مع المتغير هو توجيه المصرِّف إلى تحميل المتغير من الذاكرة RAM وليس من سجلات التخزين للذاكرة المؤقتة (الذاكرة flash) حيث تُخزَّن جميع متغيرات البرنامج. في بعض الحالات، القيمة المخزَّنة في المسجلات لمتغيرٍ ما قد تكون غير دقيقة. | الأمر الذي تفعله الكلمة <code>volatile</code> المفتاحية مع المتغير هو توجيه المصرِّف إلى تحميل المتغير من الذاكرة RAM وليس من سجلات التخزين للذاكرة المؤقتة (الذاكرة flash) حيث تُخزَّن جميع متغيرات البرنامج. في بعض الحالات، القيمة المخزَّنة في المسجلات لمتغيرٍ ما قد تكون غير دقيقة. | ||
يجب أن يعرَّف المتغير مع الكلمة <code>volatile</code> المفتاحية متى ما كان بالإمكان تغيير قيمته عبر شيء يتجاوز تحكم جزء الشيفرة الذي يظهر هذا المتغير | يجب أن يعرَّف المتغير مع الكلمة <code>volatile</code> المفتاحية متى ما كان بالإمكان تغيير قيمته عبر أي شيء يتجاوز تحكم جزء الشيفرة الذي يظهر هذا المتغير ضمنه (مثل تنفيذ خيط في وقت واحد). في أردوينو، المكان الوحيد الذي يُحتمَل أن يحدث فيه هذا الأمر هو أجزاء الشيفرة المرتبطة [[Arduino/interrupts|بالمقاطعات]] والتي تدعى [[Arduino/interrupts/attachinterrupt|ببرامج خدمة المقاطعة الفرعية]] (ISR). | ||
==الأعداد الصحيحة المتطايرة أم الطويلة المتطايرة؟== | |||
== الأعداد الصحيحة المتطايرة أم الطويلة المتطايرة؟ == | إن استعملت الكلمة <code>volatile</code> مع متغير يزيد حجمه عن بايت واحد (2 بايت مثل [[Arduino/int|عدد صحيح]]، أو 4 بايت مثل [[Arduino/long|عدد طويل]] ...إلخ.)، فلن يتمكن المتحكم من قراءته في خطوة واحدة لأنَّ معمارية المتحكم هي 8 بت غالبًا (تأكد من معمارية المتحكم في لوحتك). هذا يعني أنَّه بينما تُقرَأ أول ثمانية بتات من المتغير في جزءٍ من الشيفرة (مثل الجزء <code>[[Arduino/loop|()loop]]</code>)، قد تكون المقاطعة قد غيِّرت مسبقًا البتات الثمانية الأخرى (في حال كان حجم المتغير 16 بت). سيؤدي هذا إلى الحصول على قيمة عشوائية للمتغير. | ||
إن استعملت الكلمة <code>volatile</code> مع متغير يزيد حجمه عن بايت واحد (2 بايت مثل [[Arduino/int| | |||
حلُّ هذه المشكلة هو تعطيل المقاطعات أثناء قراءة قيم المتغيرات، وبذلك لا تتغير قيم بتات المتغير أثناء قراءتها. توجد عدة طرق لفعل ذلك منها: | حلُّ هذه المشكلة هو تعطيل المقاطعات أثناء قراءة قيم المتغيرات، وبذلك لا تتغير قيم بتات المتغير أثناء قراءتها. توجد عدة طرق لفعل ذلك منها: | ||
* استعمال الدالة <code>[[Arduino/interrupts/nointerrupts|()noInterrupts]]</code> لتعطيل المقاطعات، أو | *استعمال الدالة <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) وتمثِّل أصغر وحدة محتملة. | *استعمال الكتلة <code>[https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html ATOMIC_BLOCK]</code>، إذ العمليات الذرية (atomic operations) هي عمليات مفردة يجريها المتحكم (MCU) وتمثِّل أصغر وحدة محتملة. | ||
==أمثلة== | |||
== أمثلة == | تبديل حالة رجل متصلة مع ضوء ليد عند حدوث مقاطعة على الرجل 2:<syntaxhighlight lang="arduino"> | ||
تبديل حالة رجل متصلة مع ضوء ليد عند حدوث مقاطعة على الرجل 2:<syntaxhighlight> | |||
int pin = 13; | int pin = 13; | ||
volatile byte state = LOW; | volatile byte state = LOW; | ||
سطر 35: | سطر 34: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==انظر أيضًا== | |||
* الكلمة المفتاحية <code>[[Arduino/const|const]]</code>: هي اختصار للكلمة «ثابت» (constant)، وهي مقيِّدةٌ للمتغيرات التي تٌستعمَل معها، إذ تعدِّل سلوك المتغير لتجعله في وضع «القراءة فقط» (read-only). | |||
* الكلمة المفتاحية <code>[[Arduino/static|static]]</code>: تُستعمَل عند إنشاء متغيرات مرئيَّة لدالةٍ واحدة فقط من أجل الحفاظ على محتواها بعد انتهاء تنفيذ تلك الدالة المستدعاة وحتى الاستدعاء التالي لها خلافًا للمتغيرات المحلية التي تُنشَأ وتدمَّر في كل مرة تُستدعَى فيها الدالة. | |||
* [[Arduino/scope|مجال المتغيرات]] في أردوينو. | |||
==مصادر== | |||
*[https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/volatile/ صفحة volatile في توثيق أردوينو الرسمي.] | |||
== مصادر == | [[تصنيف: Arduino]] | ||
* [https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/volatile/ صفحة volatile في توثيق أردوينو الرسمي.] | [[تصنيف: Arduino Constants & Variables]] |
المراجعة الحالية بتاريخ 07:11، 7 نوفمبر 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;
}
انظر أيضًا
- الكلمة المفتاحية
const
: هي اختصار للكلمة «ثابت» (constant)، وهي مقيِّدةٌ للمتغيرات التي تٌستعمَل معها، إذ تعدِّل سلوك المتغير لتجعله في وضع «القراءة فقط» (read-only). - الكلمة المفتاحية
static
: تُستعمَل عند إنشاء متغيرات مرئيَّة لدالةٍ واحدة فقط من أجل الحفاظ على محتواها بعد انتهاء تنفيذ تلك الدالة المستدعاة وحتى الاستدعاء التالي لها خلافًا للمتغيرات المحلية التي تُنشَأ وتدمَّر في كل مرة تُستدعَى فيها الدالة. - مجال المتغيرات في أردوينو.