منتديات الهندسة الكهربية والإلكترونية والميكاترونكس والكومبيوتر
هل تريد التفاعل مع هذه المساهمة؟ كل ما عليك هو إنشاء حساب جديد ببضع خطوات أو تسجيل الدخول للمتابعة.

المؤقتات والمقاطعة والميكروكونترولر PIC16F877A مع المترجم CCS C :

اذهب الى الأسفل

المؤقتات والمقاطعة والميكروكونترولر PIC16F877A مع المترجم CCS C :  Empty المؤقتات والمقاطعة والميكروكونترولر PIC16F877A مع المترجم CCS C :

مُساهمة من طرف Admin في الجمعة مايو 01, 2015 1:43 pm

المؤقتات والمقاطعة والميكروكونترولر PIC16F877A مع المترجم CCS C :
يحتوى الميكروكونترولر PIC15F877A على ثلاثة مؤقتات :
• المؤقت Timer0 سعة 8 بت .
• المؤقت Timer1 سعة 16 بت .
• المؤقت Timer2 سعة 8 بت .
تستخدم المؤقتات فى كثير من التطبيقات مثل التوقيت Timing، والتقاط البيانات Capture ، وتعديل عرض النبضات PWM ، وغيرها .
يوجد سجلات تعمل كمقسم تردد سابق prescale أو لاحق postscale (فى المؤقت timer2 فقط ) للمؤقت ، يمكن التحكم فى نسبة القسمة من 1:1 إلى 1:256 بغرض تقليل التردد أو زيادة الزمن . علما بأنه إذا كان تردد المذبذب الخارجى هو Fosc يكون تردد الساعة الداخلية للميكروكونترولر Fosc/4 . فى حالة استخدام مذبذب خارجى بالقيمة 4Mhz يكون تردد الساعة الداخلية Fosc/4=4/4=1 Mhz وبالتالى يكون الزمن الدورى واحد ميكرو ثانية 1us أى نبضة كل ميكروثانية :
مثال :
العبارة التالية :
setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_4); //

تقوم بإعداد (ضبط) المؤقت Timer0 (أو يسمى RTCC) ليعمل على الساعة الداخلية ، مع معامل قسمة سابق ( ليس له معامل قسمة لاحق ) 1:4 وبالتالى فإن نبضات الساعة التى تطبق على المؤقت Timer0 فى حالة استخدام مذبذب خارجى بالقيمة 4Mhz تكون : (Fosc/4) / 4 = Fosc/16 ، ومن ثم فإننا نحصل على زمن دورى 4us ( نبضة كل أربعة ميكروثانية) بدلا من 1us .
المؤقت Timer0 هو فى حقيقة الأمر سجل بسعة 8 بت يعمل تلقائيا كعداد يتزايد بواحد فى كل مرة بدءا من الصفر (أو أى قيمة تحددها برمجيا) ويتزايد حتى يصل إلى أقصى مدى له وهو العدد “256” ، عندئذ يقال أنه مملوء ، بعد ذلك يدور إلى الصفر مرة أخرى ، هذه اللحظة تسمى overflow "تجاوز" وعندها تتولد إشارة إعلام بذلك حيث يمكن استخدامها فى توليد مقاطعة (بعد تمكينها) تستخدم فى الكثير من التطبيقات العملية .
مثال :
فى المثال السابق ونتيجة لاستخدام العبارة السابقة ، يصل إلى سجل المؤقت timer0 نبضة كل 4us (من خرج قاسم التردد السابق)، ويحدث overflow بعد وصول “256” نبضة من هذه النبضات أى بعد زمن قدرة 4 * 256 = 1024 us .
ملحوظة :
للحصول على أزمنة أطول يمكننا استخدام متغير كعداد لعدد مرات حدوث التجاوز ، كما سوف يتضح فى المثال أدناه .

استخدام المقاطعة بالمؤقت Timer0 فى توليد تأخير زمنى قيمته واحد ثانية
مبدأ العمل :
• يتم ضبط المؤقت timer0 ليعمل على الساعة الداخلية (البارامتر الأول) ، مع معامل قسمة سابق بالقيمة 1:2 (البارامتر الثانى)عن طريق العبارة التالية :
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
نتيجة لذلك ، يصل إلى المؤقت timer0 نبضة كل 2us (بدلا من 1us) .
• يتم وضع القيم “6” كقيمة ابتدائية داخل سجل المؤقت timer0 عن طريق استخدام العبارة التالية :
set_timer0(6);
نتيجة لذلك يحدث تجاوز overflow للمؤقت بعد مرور (256-6=250) نبضة وكل نبضة تستغرق 2us أى تجاوز كل (2 * 250 = 500 us) . بعد حدوث “2000” تجاوز يكون قد مر زمن قدره (500 * 2000 = 1000000 us = 1 s)

البرنامج التالى يوضح خطوات التنفيذ :

الكود:


#include <16F877A.h>
#use delay(clock=4000000)

#byte PORTB = 0x06
    int16 count;
    int8 a;

// TMR0 Interrupt
#int_timer0          // Interrupt directive
void interrupt_timer0()    // Interrupt function name
{
    set_timer0(6);       // set initial value
    ++count;         //Counter increments each overflow
    if(count == 2000)        // 2000*500us = 500000us = 1s
      {
        count=0;
        rotate_left(&a,1);
      }
}

//Main function
void main(void)
{
  set_tris_b(0); // port B as output

  enable_interrupts(int_timer0);    // Enable local  interrupt
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); // setup timer mode , prescaler
  enable_interrupts(global); // Enable global interrupt 
  set_timer0(6);// Set initial value to get overflow each 500us
 
a = 0x01;
while(true)
  {
      PORTB = a;
  }
}



يمكن وصف عمل البرنامج كما يلى :
1- فى البداية ، وكالمعتاد ، يتم وضع توجية ملف الرأس الخاص بجهاز الميكروكونترولر المستخدم بالصيغة #include <16F877A.h> ، يليه توجيه ساعة المذبذب الخارجى المستخدم بالصيغة
#use delay(clock=4000000) .
2- بعد ذلك يتم تعريف المتغيرات الشاملة global ، وهنا يتم تعريف كلمة PORTB على أنها البايت الموجود بالعنوان “0x06” بالصيغة #byte PORTB = 0x06 ، وهو العنوان الفعلى للمنفذ PORTB حتى يمكن استخدام كلمة PORTB مباشرة حيث أنها غير معرفة بهذا الشكل فى ملف الرأس ، وتعريف المتغير count نوع int16 ، والمتغير “a” نوع in8 .
3- بعد ذلك ، وقبل الدالة الرئيسية ، نصل إلى تناول المقاطعة بالمؤقت timer0 حيث نتبع الخطوات التالية :
أ‌- فى البداية ينبغى كتابة توجيه المقاطعة المستخدم بالصيغة #int_timer0 لكى نخبر المترجم بأن الدالة القادمة مباشرة void interrupt_timer0() ، هى دالة روتين خدمة المقاطعة وللقيام بعمل اللازم نيابة عنك .
ب‌- عند حدوث مقاطعة بالمؤقت timer0 نتيجة حدوث تجاوز overflow يتم تلقائيا ومن خلف الستار تنفيذ كتلة دالة خدمة المقاطعة المطلوبة . كلما حدث تجاوز يتم القيام بما يلى :
• فى البداية يتم وضع القيمة الابتدائية للمؤقت بالصيغة set_timer0(6); .
• زيادة عداد عدد مرات التجاوز بواحد بالصيغة ++count; .
• اختبار عدد مرات المقاطعة بالصيغة if(count == 2000) فإذا وصل إلى العدد “2000” وهو ما يناظر مرور زمن قدره واحد ثانية يتم تصفير العداد بالصيغة count=0; ، ثم القيام بالمهمة المطلوبة وهى هنا إزاحة محتويات المتغير بواحد جهة اليسار بالصيغة rotate_left(&a,1); . يمكن تغيير هذه المهمة بأى مهمة أخرى .
4- والآن جاء وقت الدخول إلى الدالة الرئيسية ( والتى تشير إلى بداية تنفيذ البرنامج) وفى البداية والمعتاد يتم أعداد المنافذ المطلوبة set_tris_b(0); (وتعريف المتغيرات إن وجدت) ثم نبدأ فى معالجة المقاطعة ، وفيها يتم ما يلى :
• تمكين المقاطعة ذاتها enable_interrupts(int_timer0); .
• تحديد إعدادات هذه المقاطعة setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); وهنا نحدد أن المقاطعة بالمؤقت timer0 تستخدم الساعة الداخلية ، مع استخدام معمل قسمة على “2” .
• بعد ذلك يتم تمكين جميع المقاطعات enable_interrupts(global); .
• وفى النهاية يتم وضع القيمة الابتدائية لسجل المؤقت timer0 .
5- قبل الدخول إلى الحلقة الغير منتهية يتم تخصيص قيمة “1” للمتغير بالصيغة a = 0x01; .
6- داخل الحلقة الغير منتهية يتم وضع كود المهمة الأساسية ، وهى هنا نسخ محتويات المتغير “a” إلى سجل المنفذ PORTB .
ملاحظة :
التغيير فى محتويات المتغير “a” عبارة عن إزاحة بتاته جهة اليسار موقع واحد فى كل مرة بدءا من القيمة واحد ، أى تكون المحتويات “00000001” ، ثم “00000010” وهكذا حتى “10000000” ، وهكذا نحصل على إضاءة متحركة لليدات المتصلة بالمنفذ PORTB ، كل ذلك يحدث فى خلفية البرنامج نتيجة استخدام المقاطعة بالمؤقت timer0 .

المؤقتات والمقاطعة والميكروكونترولر PIC16F877A مع المترجم CCS C :  120


Admin
Admin

عدد المساهمات : 1188
تاريخ التسجيل : 28/01/2014

https://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

الرجوع الى أعلى الصفحة


 
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى