البرنامج الثانى :
لعلاج المشكلة فى البرنامج السابق , ننشأ برنامج جديد الغرض منه التحويل بين توصيل وفصل الليد (يمثل جهاز خارجى) عند كل "ضغط ثم تحرير" للمفتاح . أى عند الضغط على المفتاح ثم تحريره يتم عكس حالة الليد , إذا ظل الضغط على المفتاح تتغير حالة المفتاح مرة واحدة فقط . زمن منع تأثير الارتدادات 20 ملى ثانية .
البرنامج :
كود:
/*
برنامج قراءة مفتاح
دورة برمجة الميكروكونترولر بلغة السى
الهدف : قراءة حالة المفتاح ومن ثم توصيل وفصل ليد تمثل جهاز خرج
إعداد :
Eng.F.Abdelaziz
http://www.eeecb.com/vb/index.php
*/
#define LED1 portd.f0 //استخدام الموجه لتخصيص (تعريف) اسم لطرف ليسهل التعامل معه
int old_state;// تعريف متغير التحكم لحفظ حالة المفتاح القديمة
void main () {
trisd.f0 = 0; // إعداد الطرف المتصل بالليد كمخرج
trisb.f0 = 1; // إعداد الطرف المتصل بالمفتاح كمدخل
do {
if (Button (& PORTB, 0, 20, 0)) old_state=1;
//إذا تم الضغط على المفتاح , ضع واحد فى متغير الحالة القديمة
if (old_state== 1 && Button (& PORTB, 0, 20, 1)) {
// التحقق من أن المفتاح قد تم تحريره(كان مضغوطا ثم حرر) وعندئذ يتم تنفيذ التالى
LED1 = ~ LED1; //عكس حالة الليد
old_state= 0; // تصفير متغير التحكم لتجهيزه للضغطة التالية
}
} while (1);
}
شرح تفاصيل البرنامج :
الجزء الأول : التعليقات
كود:
/*
برنامج قراءة مفتاح
دورة برمجة الميكروكونترولر بلغة السى
الهدف : قراءة حالة المفتاح ومن ثم توصيل وفصل ليد تمثل جهاز خرج
إعداد :
Eng.F.Abdelaziz
http://www.eeecb.com/vb/index.php
*/
الجزء الثانى : التوجيه #define
كود:
#define LED1 portd.f0 //استخدام الموجه لتخصيص (تعريف) اسم لطرف ليسهل التعامل معه
هذا التوجيه يستخدم لتخصيص (تعريف) الاسم LED1 للطرف RD0 , من هذه النقطة فى البرنامج سوف نستخدم الاسم LED1 وسوف يتعرف عليه المترجم على أنه الطرف portd.f0 (RD0)فيقوم بتغيرة وإعادته إلى أصله الطبيعى كعنوان لذاكرة الطرف RD0 .
الجزء الثالث : تعريف و تعيين المتغيرات :
كود:
int old_state;// تعريف متغير التحكم لحفظ حالة المفتاح القديمة
نعلن (نعرف) متغير من النوع int بالاسم old_state . مهمة هذا المتغير جعل الليد on/off فقط بضغطة واحدة من المفتاح , الاستمرار فى الضغط على المفتاح يتسبب فى الخروج من تعليمات if .
الجزء الرابع : الدالة الرئيسية :
الدالة الرئيسية main () هى أول ما ينفذ فى برنامج لغة السى . لاحظ أن الدالة الرئسية تلى "معرف نوعها" وهو void والذى يهدف إلى إبلاغ المترجم أن هذه الدالة "فارغة ليس لها عائد بيانات " .
الجزء الخامس :إعدادات المنافذ كمداخل ومخارج :
كود:
trisd.f0 = 0; //إعداد الطرف المتصل بالليد كمخرج
trisb.f0 = 1; // إعداد الطرف المتصل بالمفتاح كمدخل
السجل TRIS وظيفته تحديد إتجاه أطراف المنفذ (قراءة أو كتابة) . فى هذا البرنامج لدينا مفتاح متصل بالطرف RB0 , لقراءة حالة هذا المفتاح يجب إعداد الطرف كمدخل . دالة المفتاح هى المسؤلة عن تحديد هذه السجلات نيابة عنا .
لدينا ليد متصل بالطرف RD0 , يجب "إرسال" مستوى منطقى إلى هذا الطرف لذلك يجب إعداده كطرف مخرج .
الجزء السادس : روتين الحلقة الغير منتهية
تذكر أننا نحافظ على التنفيذ الدائم للبرنامج بواسطة الميكروكونترولر . فى هذا المثال نستخدم حلقة
do-while .
كود:
do {
if (Button (& PORTB, 0, 20, 0)) old_state=1;
//إذا تم الضغط على المفتاح , ضع واحد فى متغير الحالة القديمة
if (old_state== 1 && Button (& PORTB, 0, 20, 1)) {
// التحقق من أن المفتاح قد تم تحريره(كان مضغوطا ثم حرر) وعندئذ يتم تنفيذ التالى
LED1 = ~ LED1; //عكس حالة الليد
old_state= 0; // تصفير متغير التحكم لتجهيزه للضغطة التالية
}
} while (1);
لاحظ أن نتيجة اختبار شرط الحلقة يكون دائما truewhile (1)
روتين اتخاذ القرار ودالة المفتاح :
الأوامر التالية تهدف إلى قراءة حالة المفتاح S1 المتصل بالطرف RB0 بالميكروكونترولر PIC و توصيل وفصل الليد المتصل بالطرف RD0 .
الأمر الأول :
كود:
if (Button (& PORTB, 0, 20, 0)) old_state=1;
//إذا تم الضغط على المفتاح ضع واحد فى متغير الحالة القديمة
الأمر old_state=1ينفذ فقط عندما تكون نتيجة اختبار الشرط : (Button (& PORTB, 0, 20, 0) صواب true أى عندما عندما تكون نتيجة دالة المفتاح true وآخر بارامتر (الحالة الفعالة) يعنى أن نتيجة الدالة تكون صواب عند الضغط على المفتاح (حالة الدخل بصفر) .
الأمر الآخر :
كود:
if (old_state== 1 && Button (& PORTB, 0, 20, 1)) {
// التحقق من أن المفتاح قد تم تحريره وعندئذ يتم تنفيذ التالى
فى هذا السطر من البرنامج تجرى العملية المنطقية AND ( &&)بين المتغير old_state(عندما يكافىء الواحد أى بعد الضغط على المفتاح ) والعائد من دالة المفتاح Button (& PORTB, 0, 20, 1)والغرض منها هو التحقق من تحرير المفتاح . لاحظ أن آخر بارامتر فى هذه الدالة هو الواحد (فعال عند التحرير) أى أن نتيجة هذه الدالة تكون true عندما يكون المفتاح محرر . (قبلها دالة اختبار ضغط المفتاح) .
الأوامر التالية سوف يتم تنفيذها فقط عندما تكون نتيجة شرط if صواب true وهذا يستوجب أن يكون المتغير old_ state يساوى واحد وعائد دالة المفتاح بواحد أيضا أى يكون المفتاح غير مضغوط (محرر) .
عكس حالة الليد وتصفير resetحالة المتغير :
كود:
LED1 = ~ LED1; //عكس حالة الليد
old_state= 0; // تصفير متغير التحكم لتجهيزه للضغطة التالية
العامل "~" هو هو عامل يتعامل مع البتات المفردة bitwise وهو ذو معامل واحد ويقوم بعكس كل بت إذا كان المتغير بايت . المتغير هنا هو بت وهو LED1 portd.f0 . نتيجة ~ LED1 تكون عكس حالة LED1 .