قسم الميكروكنترولر والروبوت ودوائر الاتصال بالحاسب الالي قسم المتحكمات الـ microcontroller و المعالجات microprocessor و التحكم الرقمي بالكمبيوتر CNC والانظمة الآلية والروبوت Robots

   

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:21 AM المشاركة 57   
افتراضي



الدرس الرابع عشر :
التعامل مع المفاتيح فى الميكروسى
أولا : مقدمة
لا غنى عن المفاتيح فى معظم المشاريع لأنها تسمح لك بإدخال بيانات إلى الميكروكونترولر كما فى الشكل التالى .





تستخدم مقاومات داخل الميكروكونترولر تسمى "مقاومات الرفع (الجذب – الشد) لأعلى " pull-up وهى تضمن "وجود مستوى منطقى مرتفع عند طرف مدخل الميكروكونترولر عندما يكون المفتاح مفتوح" . عند الضغط على المفتاح تتحول الحالة المنطقية لطرف الدخل إلى الحالة المنخفضة لتوصيله بالأرضى كما فى الشكل السابق .
على الرغم من أن الميكروكونترولر PIC به مقاومات جذب لأعلى داخلية بالمنفذ PORTB إلا أنه يمكن أيضا استخدام مقاومات جذب لأعلى خارجية .
عندما نقوم بإنشاء مشروع به مفتاح متصل بالميكروكونترولر يجب أن نأخذ الحذر من آلية تأثير منع الارتدادات (الوثبات) debouncing عند الضغط على المفتاح .

علاج (منع ظهور) الارتدادات debouncing
تأثير المرونة الميكانيكية عند الضغط على المفتاح تسمى "إرتدادات أو وثبات" "Bouncing" والتى تتسبب فى قراءات خاطئة (مزيفة) للمفتاح نتيجة الانعكاسات التى تسبب قراءة المفتاح أكثر من مرة . روتين علاج الارتدادات ليس أكثر من فاصل زمنى صغير بين لحظة تحرير المفتاح وإعادة قراءة المفتاح . هذا المدى الزمنى يسمح بانتهاء هذه الظاهرة بشكل طبيعى , ومن ثم تجنب القراءات الزائفة . هذا الفاصل الزمنى حوالى 25 ملى ثانية . يمكن للميكروسى التعامل مع المفتاح "بدالة المفتاح" .
سوف نتناول "قراءة" المداخل الرقمية من المفاتيح الضاغطة كعينة للحساسات الرقمية. المدخل الرقمى له قيمتان فقط : القيمة واحد 1 أوالقيمة صفر 0 .

اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:25 AM المشاركة 58   
افتراضي


ثانيا : دالة المفتاح Button function


الصيغة الدالة :


كود:
unsigned short Button(unsigned short *port, unsigned short pin, unsigned short time, unsigned short active_state);
كما هو واضح أن جميع البيانات من النوع unsigned short أى فى المدى 0 .. 255 , لذلك يمكن إختصارها على الصورة التالية :

كود:
Button (& port, pin, debounce time, active_state);

حيث :
& port: إشارة للمنفذ المتصل به المفتاح .
pin : الطرف المتصل به المفتاح وقيمته من 0 إلى 7 .
debounce time : زمن منع الارتدادات بالملى ثانية .
active_state : الحالة الفعالة .

مثال :

كود:
Button (& PORTB, 0, 10, 0);
المفتاح المطلوب قراءة حالته متصل بالمنفذ PORTB بالطرف رقم 0 وهو RB0 وزمن التأخير لعلاج الارتدادات هو 10 ملى ثانية والحالة الفعالة (عند الضغط عليه) هى الحالة المنخفضة (الصفر) .

عائد (نتيجة) دالة المفتاح :
العائد يكون بالقيمة صفر false عند عدم التفعيل أى عند عدم الضغط على المفتاح (لا تتحقق حالة المفتاح المنصوص عليها فى آخر بارامتر للدالة) .
العائد يكون بالقيمة واحد true عند التفعيل أى عند الضغط على المفتاح (تتحقق حالة المفتاح المنصوص عليها فى آخر بارامتر للدالة).

اعلانات اضافية ( قم بتسجيل الدخول لاخفائها )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:28 AM المشاركة 59   
افتراضي


ثالثا : التدريبات :

البرنامج الأول :

الدائرة الكهربية :







كما فى الشكل : ميكروكونترولر PIC متصل بمفتاح ضغط push-button وليد LED .

الغرض :
فى كل مرة يتم فيها الضغط على المفتاح الضاغظ وتحريره تتغير الحالة المنطقية لليد بين التوصيل on والفصل off مع تحديد زمن التأخير لمنع الارتدادات بقيمة 20 ملى ثانية .

البرنامج :

كود:
void main () { trisd.f0 = 0; //إعداد الطرف كمخرج trisb.f0 = 1; // إعداد الطرف كمدخل do { if (Button (& PORTB, 0, 20, 0)) //إذا تم الضغط على المفتاح (العائد بواحد) يتم تنفيذ الأوامر التالية { delay_ms (200); //التأخير 200 ملى ثانية portd.f0= ~ portd.f0; // عكس حالة الليد } } while (1); }
ملخص البرنامج :
  • الإعدادات : تم إعداد الطرف RD0 كمخرج trisd.f0 = 0لاتصاله بالليد والطرف RB0 كمدخل
trisb.f0 = 1 لاتصاله بالمفتاح .
  • الحلقة الغير منتهية : تم إنشاء حلقة do-while غير منتهية حتى يعمل الميكروكونترولر بصفة مستمرة .

شرح عبارت الحلقة الغير منتهية من البرنامج :
  • فى البداية يتم تقييم دالة المفتاح if (Button (& PORTB, 0, 20, 0)) .
  • عند الضغط على المفتاح S1 يتحول طرف المنفذ المذكور بالدالة (& PORTB, 0 إلى الحالة المنخفضة (وفقا للدائرة الكهربية) ومن ثم يتحقق شرط هذه الدالة (المذكور فى آخر بارامتر ) وتعود (العائد) return بالقيمة "واحد 1 " true .
  • بينما فى حالة عدم الضغط على المفتاح الطرف المشار إليه فى الحالة المرتفعة ولا يتحقق شرط الدالة ومن ثم يكون عائدها بصفر 0 = false .
  • أى أنه عند الضغط على المفتاح يكون عائد دالة المفتاح true وبالتالى يكون نتيجة شرط if هو true ويتم تنفيذ تعليمات جملة if الموجودة بين القوسين .

كود:
{ delay_ms (200); //التأخير 200 ملى ثانية portd.f0= ~ pord.f0; // عكس حالة الليد }
  • البرنامج السابق به مشكلة , لأنه عندما " لا نحرر الضغط من على المفتاح " تكون نتيجة شرط if بالقيمة true دائما وسوف يستمر تنفيذ التعليمات فى الحلقة الغير منتهية مرارا وتكرارا وتكون النتيجة توصيل on وفصل off الليد باستمرار أثناء الضغط على المفتاح .


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:40 AM المشاركة 60   
افتراضي


البرنامج الثانى :
لعلاج المشكلة فى البرنامج السابق , ننشأ برنامج جديد الغرض منه التحويل بين توصيل وفصل الليد (يمثل جهاز خارجى) عند كل "ضغط ثم تحرير" للمفتاح . أى عند الضغط على المفتاح ثم تحريره يتم عكس حالة الليد , إذا ظل الضغط على المفتاح تتغير حالة المفتاح مرة واحدة فقط . زمن منع تأثير الارتدادات 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 .

الجزء الرابع : الدالة الرئيسية :

كود:
void main () {

الدالة الرئيسية 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 .


الصورة الرمزية هيثم العليمي
هيثم العليمي
:: مهندس جيد ::
تاريخ التسجيل: Mar 2012
الدولة: yemen
المشاركات: 236
نشاط [ هيثم العليمي ]
قوة السمعة:
قديم 20-03-2012, 02:42 AM المشاركة 61   
افتراضي


جزاك الله خير


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:44 AM المشاركة 62   
افتراضي


تعديل البرنامج :

يمكن إعادة كتابة البرنامج السابق بطريقة تسهل تتبع وفهم البرنامج بطريقة أسهل , فقط مجرد استخدام الموجه define # لتعريف دالة المفتاح فى حالة فصله باسم SWITCH_OFF وفى حالة الضغط عليه باسم SWITCH_ON كما يلى :


كود:
sbit LED at PORTD.B0; #define SWITCH_OFF Button(&PORTB, 0, 1, 1) #define SWITCH_ON Button&)PORTB, 0, 1, 0( bit oldstate; // Old state flag
void main() {
TRISB.B0 = 1; // set RB0 pin as input TRISD = 0x00;// Configure PORTD as output PORTD = 0x00; // Initial PORTC value oldstate = 0; do { if (SWITCH_OFF) oldstate = 1; // Detect logical one , Update flag if (oldstate && SWITCH_ON) { // Detect one-to-zero transition LED= ~LED;//Invert OUTPUT oldstate = 0; //Update flag } } while(1);//Endless loop }


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:47 AM المشاركة 63   
افتراضي


البرنامج الثالث :

الغرض :
هذا البرنامج يعرض استخدام مفتاح متصل بالمنفذ PORTB كمدخل على الطرف RB0 . عند كل تغير (تحول انتقال) فى حالة الطرف RB0 من الواحد (1) إلى الصفر يتم عكس حالة جميع خانات المنفذ PORTD .
· الميكروكونترولر المستخدم PIC16F877A .
· تردد المذبذب 4MHz
· المترجم mikroC PRO for PIC
· يتم التحكم فى إضاءة وإطفاء الليدات المتصلة بالمنفذ PORTD .
الدائرة الكهربية :


البرنامج :



كود:
bit oldstate; // Old state flag void main() { TRISB0_bit = 1; // set RB0 pin as input TRISD = 0x00; // Configure PORTC as output PORTD = 0xAA; // Initial PORTD value oldstate = 0; do { if (Button(&PORTB, 0, 1, 0)) { // Detect logical ZERO oldstate = 1; // Update flag } if (oldstate && Button(&PORTB, 0, 1, 0)) { // Detect one-to-zero transition PORTD = ~PORTD; // Invert PORTD oldstate = 0; // Update flag } } while(1); // Endless loop }
شرح البرنامج :

1- إعلان عن متغير فى شكل بت واحدة bit oldstate"الحالة القديمة"لحفظ حالة المفتاح ومقارنتها بحالة أجدد منها .
2- الدالة الرئيسيةvoid main() { وتتضمن :
أ‌- إعداد المنافذ :
· إعداد الطرف الأول من المنفذ PORT B كمدخل (لاحظ طريقة استخدام خانة مفردة )TRISB0_bit = 1 .
· إعداد جميع أطراف المنفذ PORT D كمخارج TRISD = 0x00 .
· القيمة الابتدائية للمنفذ PORTC = 0xAA = 0b10101010 (مثال لنموذج )
· الحالة الابتدائية لبت الحالة هى الصفر oldstate = 0 لتهيئتها لبدء العمل.
ب‌- إنشاء حلقةdo{….}while الغير منتهية وبداخلها :
· كشف حالة المفتاح باستخدام عبارة الشرط : هل المفتاح منضغط ؟
if (Button(&PORTB, 0, 1, 0)) .
· إذا كان المفتاح منضغط تكون حالة طرف المفتاح الفعال هى الصفر (كما هو مبين بأخر بارامتر) وتعود دالة المفتاح بواحد ويتحقق شرط if ويت تنفيذ العبارة التالية أى فعالية الضغط كواحد فى متغير حالة البت oldstate = 1 بعد أن كان بالصفر حتى يمكن مقارنتها بحالته إذا تغيرت .
· إكتشاف الانتقال من الصفر (الضغط) إلى الواحد (التحرير) ؟ نستخدم فى ذلك العملية المنطقية AND (&&) بين الخانة oldstate = 1 بحالتها السابقة (الحالة المرتفعة) وحالة المفتاح بعد تمام تحريره (فى الحالة المنخفضة إى غير مفعل)
يحقق شرط if إذا كان كل من جانبى المؤثر && متحقق عندئذ يتم عكس حالة أطراف المنفذ PORTD و عودة البت الخانة oldstate إلى حالة الصفر للتجهيز لحالة قادمة .


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 20-03-2012, 02:50 AM المشاركة 64   
افتراضي


البرنامج الرابع :
قراءة 4 مفاتيح :
خطوتنا التالية هى تصميم برنامج لقراءة 4 مفاتيح متصلة بالميكروكونترولر كما فى الشكل التالى :

لاحظ من الشكل عدم استخدام مقاومات رفع لأعلى خارجية وبالتالى يجب تفعيل مقاومات الرفع لأعلى الداخلية المرتبطة بالمنفذ PORTB من خلال البت RBPU بالسجل INTCON2 .
المنفذ PORTB للميكروكونترولر PIC16F877A (على سبيل المثال) به دائرة مقاومات جذب لأعلى داخلية "غير مفعلة"disabledفى "الوضع الافتراضى" default ( بعد عملية الإعادة reset ) . هذه المقاومات يتم تفعيلها تلقائيا عند برمجة المنفذ PORTB كمخارج(TRISB = 0) , فى باقى الحالات نقوم بتمكينها بأنفسنا .
يتم تمكين enable البت RBPU( البت 7 بسجل الخياراتOPTION_REG.B7 ) بجعلها فى المستوى المنطقى المنخفض low (الصفر) , ويتم تعطيلها (عدم تمكينها) disable بجعلها فى المستوى المنطقى المرتفع high(واحد) .

البرنامج :


كود:
/* برنامج قراءة 4 مفاتيح دورة :برمجة الميكروكونترولر بلغة السى الغرض : قراءة حالة 4 مفاتيح للتحكم فى توصيل وفصل ليدات (أجهزة خرج) إعداد : Eng.F.Abdelaziz http://www.eeecb.com/vb/index.php */ # define LED1 portd.f0 //إستخدام متجه التعريف لتخصيص إسم لطرف بمنفذ int old_state; // تعريف متغير التحكم لحفظ حالة المفتاح القديمة void main () { TRISD = 0; //إعداد جميع أطراف المنفذ المتصل بالليدات كمخارج PORTD = 0; //تصفير أطراف منفذ الخرج OPTION_REG.B7= 0; //RBPU=BIT 7 تمكين المقاومات الداخلية للرفع لأعلى trisb.f0 = 1; // إعداد الطرف المتصل بالمفتاح كمدخل trisb.f1 = 1; // إعداد الطرف المتصل بالمفتاح كمدخل trisb.f2 = 1; // إعداد الطرف المتصل بالمفتاح كمدخل trisb.f3 = 1; // إعداد الطرف المتصل بالمفتاح كمدخل do { if (Button (& PORTB, 0, 20, 0)) // المفتاح الأول PORTD = 0b00000001; else if (Button (& PORTB, 1, 20, 0)) //المفتاح الثانى PORTD = 0b00000010; else if (Button (& PORTB, 2, 20, 0)) //المفتاح الثالث PORTD = 0b00000100; else if (Button (& PORTB, 3, 20, 0)) //المفتاح الرابع PORTD = 0b00001000; Delay_ms (200); //تأخير 200 ملى ثانية } while (1); }



الساعة معتمدة بتوقيت جرينتش +3 الساعة الآن: 04:54 PM
موقع القرية الالكترونية غير مسؤول عن أي اتفاق تجاري أو تعاوني بين الأعضاء
فعلى كل شخص تحمل مسئولية نفسه إتجاه مايقوم به من بيع وشراء وإتفاق وأعطاء معلومات موقعه
التعليقات المنشورة لا تعبر عن رأي موقع القرية الالكترونية ولايتحمل الموقع أي مسؤولية قانونية حيال ذلك (ويتحمل كاتبها مسؤولية النشر)