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

أدوات الموضوع

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 25-07-2017, 07:37 PM المشاركة 1   
افتراضي المؤقتات Timers والعدادات Counters Twitter FaceBook Google+



المؤقتات Timers والعدادات Counters
الميكروكونترولر PIC مجهز بوحدة (موديول) أو أكثر للتوقيت الدقيق تعرف باسم المؤقتات Timers والتى يمكن استخدامها لتنفيذ مجموعة متنوعة من وظائف التوقيت الدقيقة مثل توليد أحداث في أوقات محددة ، وقياس مدة (فترة دوام) duration حدث وحفظ تسجيل التاريخ والوقت وعد الأحداث counting وما إلى ذلك.
العنصر الرئيسي فى وحدة (موديول) المؤقت هو "عداد ثنائى حر يتزايد عند كل نبضة ترد إليه" ، ونظرا لأنه يعمل بشكل مستقل فإنه يمكن أن يعد النبضات فى وقت واحد (بالتزامن) مع تنفيذ البرنامج الرئيسي .
يمتلك الميكروكونترولر PIC16F877A ، على سبيل المثال ، ثلاثة من المؤقتات كأجهزة hardware مدمجة به وتسمى Timer0 و Timer1و Timer2 وسوف نتناول فى هذا الدرس وحدة (موديول) المؤقت Timer0.

وحدة (موديول) المؤقت / العداد Timer 0 :
وحدة (موديول) المؤقت / العداد timer/counter module ببساطة هى عداد ثنائى binary counter مستقل والذى يمكن تهيئته (إعداده) لكى يقوم بعد نبضات ساعة دورات التعليمات الداخلية ( تردد الكريستال مقسوما على 4 ) أو عد نبضات ساعة خارجية .
المؤقت Timer 0 هو عداد متزامن بسعة 8 بتات 8-bit والذى يقوم بحفظ (تخزين) قيمة العداد فى سجل وظائف خاصة يسمى TMR0 . هذا السجل قابل للقراءة وللكتابة فى أى وقت عن طريق البرنامج . إذا كتبت قيمة عليه فسوف يبدأ العداد التزايد من هذه القيمة .
عندما يتم تشغيل الموديول Timer 0 بنبضات ساعة تعليمات المعالج فيقال أنه يعمل كمؤقت timer لأنه يتزايد بمعدل ثابت ( يتحدد بنبضات ساعة المعالج) ، وإذا علمت عدد النبضات التى قام بعدها يمكنك إشتقاق (إستنتاج) الوقت المنقضى .
يمكن للمؤقت Timer 0 أيضا عد النبضات الخارجية الواصلة إلى الطرف RA4 المسمى
T0CKI (Timer Zero Clock Input) " مدخل نبضات الساعة للمؤقت صفر " . عندما يقوم الموديول بعد النبضات الخارجية يقال أنه يعمل كعداد counter . سوف نناقش نظامى العمل كل على حدة .

نظام المؤقت Timer mode



• يتم اختيار نظام المؤقت بمسح clear البت T0CS " بت اختيار مصدر ساعة المؤقت Timer0 " وهى البت 5 بسجل الخيارات : (OPTION register, bit 5) إى T0CS=0.
• فى نظام المؤقت يتزايد السجل TMR0 عند كل دورة تعليمة ، ولأن هذا السجل ذو سعة 8-bit فيمكنه العد من الصفر 00 إلى FF (255) ، وعندما يصل إلى أقصى قيمة له وهى FF (255) ويتقدم (يتجاوز) فى التزايد يعود للعد من الصفر 00 من جديد وتعرف هذه الحالة بالطفحان overflow (تجاوز الحد الأقصى) ويتم تسجيل هذه الحالة عن طريق "رفع علم أو راية البت T0IF " بت علم مقاطعة المؤقت Timer0 " (Timer0 Interrupt Flag) وهى البت 3 بسجل التحكم فى المقاطعة : (INTCON,bit 3) (Interrupt Control) وذلك بجعلها بالقيمة set أى T0IF=1 ، حيث يمكن لهذه الحالة بدء (توليد) مقاطعة والتى تعرف باسم " المقاطعة بالمؤقت صفر " Timer0 Interrupt إذا ما كانت ممكنة لعمل مقاطعة .
• يتم تمكين مقاطعة المؤقت Timer0 بجعل البت T0IE (Timer0 Interrupt Enable) " تمكين المقاطعة بالمؤقت صفر " بسجل التحكم فى المقاطعة ( INTCON,bit5) بجعلها بالقيمة set أى T0IE=1 بالأضافة إلى خانة التمكين العام GIE ( INTCON,bit7). هذه المقاطعة هى التى يجب أن تبين أن الوقت إنتهى وتحدث عند حدوث طفحان بالسجل TMR0 .
• يجب مسح clear الخانة T0IF " علم مقاطعة المؤقت صفر " بواسطة روتين خدمة المقاطعة بحيث يمكن حدوث مقاطعة بالمؤقت من جديد أى T0IF=0.
مثال :
نفترض أن الميكروكونترولر PIC يعمل على مذبذب ساعة بتردد Fosc =4 MHz فإن تردد نبضات ساعة التعليمات سوف تكون Fosc /4 = 1 MHz . نتيجة لذلك يقوم العداد بالتزايد كل واحد ميكروثانية 1 μs بالضبط . وهذا يعنى أن المؤقت Timer0 سوف يستغرق 256 μs لكى يعد من الصفر إلى الصفر التالى .
عن طريق تحميل سجل المؤقت TMR0 بقيمة مسبقة مناسبة يمكن اختيار فترات زمنية أصغر .على سبيل المثال إذا تم تحميل السجل TMR0 مسبقا بالقيمة 206 فإن المؤقت Timer0 سوف يحدث له طفحان بعد 50 μs فقط .

• علاوة على ذلك يوجد قاسم تردد مبرمج بسعة 8-bit يعرف باسم prescaler "المقياس المسبق " أو " معامل القسمة " وهو متاح لقياس الفترات الزمنية الطويلة . والمقياس المسبق هو دائرة قسمة تقع بين مصدر نبضات الساعة والمؤقت وتقوم بقسمة التردد الداخل إلى المؤقت على قيمة من ثمانى قيم ثنائية تقع ما بين القيمة 2 والقيمة 256 .

مثال :
إذا كان تردد نبضات ساعة التعليمات 1MHz فإن أقصى فترة زمنية تناظر أكبر معامل قسمة وهو 256 أى :

كود:
 256 x 256 μs = 65.536 ms
• قيم معامل القسمة يتم اختيارها برمجيا بواسطة البتات الثلاثة : PS0, PS1,PS2 " بتات اختيار معامل القسمة " بسجل الخيارات (OPTION,bit0-bit2) .

• من أجل تخصيص استخدام معامل القسمة مع موديول المؤقت Timer0 يجب مسح clear = 0 البت PSA " تخصيص معامل القسمة " أى PSA=0. إما إذا كانت الخانة PSA بواحد set = 1 فلا يتم تخصيص أى معامل قسمة لموديول المؤقت (1 : 1 ) .

فيما يلى تفاصيل سجل الخيارات OPTION_REG وسجل التحكم فى المقاطعة INTCON للرجوع إليها عند الحاجة:






نظام العداد Counter Mode
يتم اختيار نظام العداد بجعل البت T0CSبالسجل OPTION بواحد set = 1 أى T0CS=1.
فى هذا النظام يقوم موديول المؤقت Timer0 بعد نبضات الساعة الخارجية الموجودة على الطرف RA4/T0CKI. يتزايد المؤقت سواء عند الحافة الصاعدة أو عند الحافة الهابطة لنبضات الساعة ويتم اختيار ذلك برمجيا بواسطة البت T0SE (Timer0 Source Edge) " حافة مصدر المؤقت صفر " بسجل الخيارات (OPTION,bit4) . إذا كانت هذه البت بواحد set أى T0SE=1 فسوف يتزايد المؤقت عند الحافة الهابطة لكل نبضة من نبضات الساعة التى تصل إلى الطرف RA4/T0CKI (عند الانتقال من الحالة المرتفعة إلى الحالة المنخفضة ) . مرة أخرى يمكن توسعة أو تمديد مدى العداد باستخدام prescaler .

احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى ( أعجبته المشاركة )
اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 25-07-2017, 07:45 PM المشاركة 2   
افتراضي


التدريب على نظام المؤقت :
مقدمة :
فى البداية سوف نتناول خطوة بخطوة إعداد الأجزاء المختلفة لموديول المؤقت باستخدام سجل الخيارات OPTION_REG :
1- اختيار مصدر المؤقت Timer كما فى الشكل التالى :



البت T0CS : بت اختيار مصدر ساعة المؤقت Timer0 .
T0CS=1 : نظام العداد : الإشارة الموجودة على الطرف T0CKI (Timer0 Clock Input) تستخدم كمصدر للمؤقت Timer0 .
T0CS=0 : نظام مؤقت : تستخدم ساعة التعليمات الداخلية كمصدر للمؤقت Timer0 .
ملحوظة :
دورة التعليمات الداخلية تساوى تردد مذبذب الميكروكونترولر مقسوم على أربعة Fosc/4 .

2- اختيار حافة المصدر ( للمصدر الخارجى فقط أى فى نظام العداد) :
البت T0SE : بت اختيار حافة مصدر المؤقت Timer0 .
T0SE=1 : يتزايد السجل TMR0 عند إنتقال حالة الطرف T0CKI من الحالة المرتفعة إلى الحالة المنخفضة ( الحافة الهابطة) .
T0SE=0 : يتزايد السجل TMR0 عند إنتقال حالة الطرف T0CKI من الحالة المنخفضة إلى الحالة المرتفعة ( الحافة الصاعدة) .



3- تخصيص وإعداد معامل قسمة التردد Prescaler :
يخصص معامل القسمة عن طريق البرنامج إما للمؤقت Timer0 أو لمؤقت الحراسة . لتخصيص معامل القسمة للمؤقت Timer0 يجب مسح خانة التخصيص PSA .
البت PSA : بت تخصيص معامل القسمة Prescaler .
PSA=1 : تخصيص معامل القسمة لمؤقت الحراسة .
PSA=0 : تخصيص معامل القسمة لموديول المؤقت Timer0 .



قيمة معامل القسمة prescaler سوف تحدد كم عدد حواف المصدر سوف تؤدى إلى تزايد السجل TMR0 بواحد . يمكن إعداد معامل القسمة ليأخذ أحد قيم النسب الثمانية من 1:1 إلى 1:256 .
البتات PS2:PS0 : بتات اختيار معدل معامل القسمة Prescaler.

4- أعدادات مقاطعة المؤقت TIMER0
تمهيد:
سوف يأتى الوقت الذى تريد فيه أن يكرس المعالج إهتمامه ، نتيجة لوقوع حدث ما ، لمهمة أخرى (غير مهمته العادية التى يقوم بها) ويقوم بخدمتها مثل زيادة متغير عداد عندما يرتفع علم مقاطعة المؤقت T0IF نتيجة حدوث تجاوز overflow بسجل المؤقت TMR0 بدون الحاجة للتحقق من حالتها بصفة مستمرة .
يمكن تحقيق ذلك بسهولة عن طريق روتين خدمة المقاطعة “ISR”.
عندما تحدث المقاطعة ، ويمكن أن يكون هناك أكثر من مقاطعة ، يتوقف المعالج على الفور عما يفعل فى البرنامج العادى ويقفز إلى روتين خدمة المقاطعة لخدمة المقاطعة . بمجرد الانتهاء من تقديم هذه الخدمة يعود المعالج إلى ما كان يفعله فى البرنامج العادى قبل المقاطعة .

إعداد مقاطعة المؤقت TIMER0 :
يمكن الإعداد لتوليد مقاطعة عندما يتجاوز السجل TMR0 العد من 255 إلى 0 ويتم ذلك عن طريق سجل التحكم فى المقاطعة INTCON كما فى الشكل التالى :




يتم إعداد إى مقاطعة عن طريق ثلاثة بتات أساسية :
• البت الأولى : "بت تمكين عموم المقاطعة" (GIE) , ويجب تمكينها GIE=1 لأن الحالة الافتراضية لها هى عدم التمكين GIE=0 . هذه البت تعمل كنوع من المفتاح الرئيسى الذى يجب رفعه (توصيله) set , GIE=1لتمكين قدرة الميكروكونترولر على المقاطعة . هذه البت سوف يتم مسحها clear "تلقائيا " GIE=0 كلما حدثت مقاطعة لضمان عدم حدوث أى مقاطعة أخرى خلال تنفيذ روتين خدمة المقاطعة . الحالة الافتراضية لهذه البت هى عدم التمكين GIE=0 .
لذلك بمجرد أن يكتمل روتين خدمة المقاطعة يجب جعل هذه البت GIE=1 مرة أخرى لتمكين المقاطعات فى المستقبل .
• البت الثانية : " بت تمكين المقاطعة بالمؤقت Timer0 " (T0IE) ، ويجب تمكينها T0IE=1 لأن الحالة الافتراضية لهذه البت هى عدم التمكين T0IE=0 .
• البت الثالثة : " بت علم تجاوز المؤقت Timer0" (T0IF) . عند حدوث تجاوز Overflow تتحول هذه البت إلى الحالة المرتفعة T0IF=1 وتظل على هذه الحالة حتى يتم مسحها عن طريق البرنامج . هذه البت تحتاج لمسحها إذا كنا نريد مقاطعة أخرى T0IF=0.
ينصح باتباع الخطوات التالية عند إعداد أى مقاطعة وتتبع أى روتين خدمة المقاطعة :
1- مسح clear بت علم المقاطعة ، وهى هنا T0IF=0 .
2- تمكين بت المقاطعة بالموديول المحدد ، وهى هنا T0IE .
3- تمكين بت عموم المقاطعة GIE=1 .
الإعداد بهذه الخطوات سوف يضمن عدم حدوث المقاطعة خلال التهيئة للبدء والذى يتسبب فى نتائج غير متوقعة .

مثال لروتين خدمة مقاطعة المؤقت Timer0 (مثال المترجم ميكروسى برو) :
فيما يلى مثال بسيط للتعامل مع المقاطعات من المؤقت TMR0 ( إذا لم يسمح لمقاطعات أخرى ) :

كود:
 void interrupt() {
  counter++;
  TMR0 = 96;
INTCON.TMR0IF = 0; //TMR0 interrupt flag must be cleared in software
//to allow subsequent interrupts

}
فى حالة تمكين مقاطعات متعددة ، تحتاج لاختبار المقاطعات التى تقع ، ومن ثم تقديم الكود المناسب :

كود:
void interrupt() {
  if (INTCON.TMR0IF) {    //are TMR0 interrupts enabled
    counter++;
    TMR0 = 96;
    INTCON.TMR0IF = 0;
  }
  else if (INTCON.RBIF) {
    counter++;
    INTCON.RBIF = 0;
  }
}
مثال آخر :

كود:
 
// In this example, TMR0 is configured as a timer and prescaler is assigned to it.
    
unsigned cnt;          // Define variable cnt
void interrupt() {     // Interrupt routine
    cnt++;             // Interrupt causes cnt to be incremented by 1
    TMR0 = 155;        // Timer (or counter) TMR0 returns its initial value
    INTCON = 0x20;     // Bit T0IE is set, bit T0IF is cleared
}
 
void main() {
    OPTION_REG = 0x04; // Prescaler (1:32) is assigned to the timer TMR0
    TMR0 = 155;        // Timer T0 counts from 155 to 255
    INTCON = 0xA0;     // Enable interrupt TMR0
    ...
    ...
    
    // In the following example,TMR0 is configured as counter and prescaler is assigned to it
    
    OPTION_REG = 0x20; // Prescaler (1:2) is assigned to the counter TMR0
    TMR0 = 155;        // Counter T0 counts from 155 to 255
    INTCON = 0xA0;     // Enable interrupt TMR0
    ...
    ...
باختصار :
من أجل استخدام المؤقت TMR0 بشكل صحيح ينبغى :
الخطوة الأولى : اختيار نظام العمل :
• يتم اختيار تظام عمل المؤقت عن طؤيق البت T0CS بالسجل OPTION_REG ، T0CS: 0=timer ، T0CS: 1= counter .
• عند الاستخدام ، يجب تخصيص معامل القسمة prescaler للمؤقت / العداد عن طريق مسح (0) البت PSA بالسجل OPTION_REG . يتم تحديد معدل معامل القسمة عن طريق البتنات PS2-PS0 بنفس السجل .
• عند استخدام المقاطعة ، يجب تحديد (1) البتات GIE و TMR0IE بالسجل INTCON .
الخطوة الثانية : القياس والعد
لقياس الزمن :
• قم بعمل Reset (صفر) للسجل TMR0 أو اكتب إليه قيمة معروفة .
• يتم قياس الزمن المنقضى (بالميكروثانية عندما تستخدم كريستال بتردد 4MHz ) عن طريق قراءة السجل TMR0 .
• بت العلم TMR0IF بالسجل INTCON يتم تلقائيا تحديدها (1) فى كل مرة يحدث طفحان overflow فى السجل TMR0 ، إذا كان قد تم تمكينها ، وتحدث مقاطعة .
لعد النبضات :
• يتم اختيار قطبية النبضات المراد عدها من على الطرف RA4 عن طريق البت T0SE بالسجل OPTION_REG ، (T0SE: 0=positive, 1=negative pulses) .
• يمكن قياس عدد النبضات عن طريق قراءة السجل TMR0 . يتم استخدام معامل القسمة والمقاطعة بنفس إسلوب نظام المؤقت .

احصائية الشكر والاعجاب - 2 شكراً, 0 عدم اعجاب, 2 اعجاب
شكراً سعيد قادر, عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب سعيد قادر, عبدالله حجازى ( أعجبته المشاركة )
اعلانات اضافية ( قم بتسجيل الدخول لاخفائها )
  

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 25-07-2017, 10:10 PM المشاركة 3   
افتراضي


تدريب على نظام عمل موديول المؤقت Timer0 كمؤقت Timer:



توليد تأخير زمنى بحوالى واحد ثانية باستخدام موديول Timer0 كمؤقت . تردد الكريستال 4 MHz لذلك يكون زمن دورة التعليمة هو واحد ميكروثانية 1s . لتوليد فترة تأخير بقيمة واحد ثانية يجب أن يعد المؤقت مليون دورة 1000000 . إذا استخدمنا "معامل قسمة" prescaler بالقيمة 256 فإن العد المطلوب يقل إلى 3906 . والآن إذا قمنا بتحميل سجل المؤقت TMR0 بقيمة ابتدائية قدرها 39 فإنه سوف يحدث له طفحان overflow بعد عدد من العد قدره 256-39 = 217 counts . ومن ثم يكون عدد مرات الطفحان اللازمة هى 18 مرة كما يلى :

كود:
 3906 counts = 3906/217 = 18
بهذه الإعدادات بعد كل 18 مرة طفحان لسجل المؤقت TMR0 (مع تحميله مسبقا بالقيمة 39) يكون قد إنقضى فترة زمنية قدرها واحد ثانية تقريبا . لمشاهدة النتيجة نجعل هذا الزمن يتسبب فى عمل وميض لليد .
الدائرة الكهربية :



البرنامج :
فى البداية نلقى نظرة على إعدادات سجل الخيارات وسجل التحكم فى المقاطعة :




كود:
 
/*PIC16F877A
1sec timer using TIMER0
Oscillator * 4MHz
*/
// Define LED connection
sbit LED at RB0_bit;
unsigned short Num;// overflow counter 0 .. 18

// Interrupt service routine
void interrupt(){
  Num ++;           	// Interrupt causes Num to be incremented by 1
  if(Num == 18){ 	// after 1 sec period
   LED = ~LED;       	// Toggle LED every sec
   Num = 0;		//clear again
  }
  TMR0 = 39;        	// TMR0 returns to its initial value
  INTCON.T0IF = 0; // Bit T0IF is cleared so that the interrupt could reoccur
}

void main() {
 TRISB = 0b00000000; // PORTB All Outputs
LED = 0;
 Num = 0; // begin 
 OPTION_REG = 0x07; 	// Prescaler (1:256) is assigned to the timer TMR0
 TMR0 = 39;          		// Timer T0 counts from 39 to 255
 INTCON = 0xA0;     	// Enable interrupt TMR0 and Global Interrupts
 do {
 // Your main programs goes here
 } while(1);  			// infinite loop
}

احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى ( أعجبته المشاركة )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 25-07-2017, 10:19 PM المشاركة 4   
افتراضي


التدريب على نظام عمل موديول المؤقت Timer 0 كعداد counter :
سوف نستخدم موديول المؤقت Timer0 كعداد لعد نبضات الساعة الخارجية والتى تصل عن طريق الطرف RA4/T0CKI . نبضات الساعة الخارجية سوف يتم اشتقاقها من منبع التيار المتردد . منبع التيار المتردد المستخدم جيبى ذو جهد وتردد 220V, 50 Hz .
سوف يتم أولا تخفيض الجهد إلى إشارة بجهد وتردد 9 V, 50 Hz باستخدام محول تيار متردد . وقبل توصيل هذه الإشارة إلى الطرف T0CKI يجب تقويمها (توحيدها) وقطع (قص – تحديد) قيمة جهد الذروة عند +5V . الدائرة التالية تحول الجهد 9 V, 50 Hz AC voltage إلى موجة مربعة تقريبا بجهد +5V مناسبة كمدخل للعداد من الطرف T0CKI .



يتم توصيل الموجة المربعة إلى الطرف RA4/T0CKI للميكروكونترولر PIC16F877A . يبدأ السجل TMR0 من الصفر ويعد النبضات الواصلة فى فترة زمنية قدرها واحد ثانية . يتم عرض النتيجة على شاشة وحدة عرض LCD .عدد النبضات فى الثانية هو تردد الإشارة الواصلة وهو 50 Hz .
الدائرة الكهربية :




البرنامج :



كود:
/*
Timer0 as a counter
Oscillator * 4MHz */

// LCD module connections
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections

// Define Messages
char message1[] = "Frequency=   Hz";
char *freq = "00";


void Display_Freq(unsigned int freq2write) {
 freq[0] = (freq2write/10)%10 + 48;   // Extract tens digit-add 48 >> change to ASCII 
 freq[1] =  freq2write%10     + 48;     // Extract ones digit add 48 >> change to ASCII 
 // Display Frequency on LCD
 Lcd_Out(1, 11, freq);
}

void main() {

TRISB = 0; // PORTB All Outputs
TRISA = 0XFF; // INPUTS 
 
 OPTION_REG = 0b00101000; // Prescaler (1:1), TOCS =1 for counter mode

 Lcd_Init();                 // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);        // CLEAR display
 Lcd_Cmd(_LCD_CURSOR_OFF);   // Cursor off
 Lcd_Out(1,1,message1);      // Write message1 in 1st row
 do {

  TMR0=0;
  Delay_ms(1000);  // Delay 1 Sec TIMER0 COUNT=Hz

  Display_Freq(TMR0);

 } while(1);  // Infinite loop
}
النتائج :




احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى ( أعجبته المشاركة )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 25-07-2017, 10:31 PM المشاركة 5   
افتراضي


برنامج متعدد المهام :
الدائرة الكهربية :



يقوم البرنامج بعمل مهمتين فى نفس الوقت ، المهمة الظاهرة والعادية هى إصدار صوت من سماعة بصفة مستمرة ، ومهمة فى الخلفية وهى وميض ليد عن طريق توليد نبضة كل واحد ثانية باستخدام موديول المؤقت Timer0 كمؤقت والمقاطعة بهذا المؤقت .

كود:
/*Name : LED & SOUNDER
PICMICRO : PIC16F877A
 */
// Interrupt Routine Service IRS
/* This routine, having the attribute "interrupt" 
which called automatically whenever an interrupt occurs. 
in this routine , Timer0 will generate an interrupt every millisecond */ 

void interrupt (  )
{
   if( T0IF )  			// Interrupt was caused by an overflow of Timer0?
      {
      TMR0 =  100 ;  		// Timer0 reloaded
      TimerLed ++;  		// Increment the timer for the blinking LED
      if( TimerLed >= TEMP_LED )  // If the time has passed TEMP_LED=250
         {
         LED = ~LED ;  		// Invert LED status to flash .
         TimerLed = 0 ;  		// Reloading the LED timer to start again
       }
      T0IF = 0 ;  			// Reset the interrupt flag of timer 0
      }				  // end that occurred on Timer0 interrupt
}				  // end of interrupt service routine

// definitions
#define TEMP_LED 250    	// Constant value , 250 ,defined as "TEMP_LED .   
#define LED PORTD.B0 	//LED at pin RD0=PORTD.B0 defined as "LED" '
#define BUZZER PORTD.B1 	//SOUNDER at pin RD1 = PORTD.B1 defined as "BUZZER" .
#define T0IF INTCON.T0IF	//Timer0 Interrupt Flag Bit INTCON.F0IF defined as "T0IF"

// Variable decleraion 
unsigned char TimerLed = 0;
/*Variable : Char data type is an 8-bit so it can get to hold values up to 255
     we need a maximum of 250,TEMP_LED , so it's fine */
  
// Setting Function 
void settings ( void ) 		// Setting Function
{
//PORTS Setting
 TRISD = 0 ;		// PORTD as outputs
// Setting the OPTION register 
OPTION_reg = 0b11000100 ;
// bit 0 -> Prescaler Rate Select bit 0  >0
// bit 1 -> Prescaler Rate Select bit 0  >0
// bit 2 -> Prescaler Rate Select bit 0  >1  (3 bits 100= 1:32)
// bit 3 -> Prescaler assigned to Timer0 >0
// bit 4 -> It does not matter  >0 
// bit 5 -> Timer0 Clock derived from internal clock cycle >0
// bit 6 -> It does not matter >1
// bit 7 -> pull-up resistors on port B disabled >1

// Set interrupt
INTCON = 0b10100000;
// bit 0 -> RBIF - Flag of interrupt ports B   >0
// bit 1 -> INTF - Interrupt Flag of RB0/INT  >0
// bit 2 -> T0IF - on Timer0 interrupt flag  >0
// bit 3 -> RBIE, Interrupt on Port B disabled  >0
// bit 4 -> INTE, Interrupt port RB0/INT disabled >0
// bit 5 -> TMR0IE, Interrupt on Timer0 enabled    >1 
// bit 6 -> PEIE, interrupt device disabled  >0  
// bit 7 -> GIE, Management Interrupt active       >1

TMR0 = 100 ;  // Set Timer0 to 100 , as initial value
}

// main function 
void main ( )
{
   settings ( ) ;  		// Run Setting Function for ports and registers
   while ( 1 )  		// run a loop 
   {

/* The only thing that I do during this endless cycle,
is the reversal of the state of BUZZER each 200 micro-sec 
in order to generate a square wave of 2.5 KHz,
which applied at the buzzer, 
in fact, causing it to emit a note at that frequency*/

      Delay_us ( 200);
      BUZZER = 1;
      Delay_us ( 200);
      BUZZER = 0;
   }// end loop
}  // end main

احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى ( أعجبته المشاركة )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 26-07-2017, 01:30 PM المشاركة 6   
افتراضي


أفضل طريقة لانتخاب وحدات العرض 7-Segment عن طريق مقاطعة المؤقت TIMER0
عرض جميع وحدات العرض فى نفس الوقت غير ممكن لأن كل وحدة تمثل رقم أو خانة لها معلومات مختلفة مطلوب عرضها ، الحل هو عرض وحدة واحدة فى كل مرة . إذا تم عرض جميع الوحدات بتتابع سريع فسوف تظهر بالنسبة للعين كما لو كانت تعرض فى نفس الوقت ، هذه الطريقة تسمى "الانتخاب" multiplexing .



من الأفضل تنفيذ خوارزمية الانتخاب باستخدام مقاطعة المؤقت TIMER0 . عن طريق جعل السجل TMR0 يحدث له طفحان overflow وتوليد مقاطعة كل 5 ms ، حيث يمكن عرض كل وحدة كل 5 ms ومن ثم يكون الزمن الكلى للعرض حوالى 20 ms (4 x 5ms) وهذا الزمن بالفعل كافى لتجنب الإرتعاش الذى يمكن أن يظهر للعين .
عداد تصاعدى تنازلى باستخدام 2 و 4 وحدةعرض 7 SEGMENT
الدائرة الكهربية :



ملاحظات :
• وحدات العرض من نوع الأنود المشترك ، أنودات الوحدات (الخانات) DIG1-DIG4 متصلة بالمنفذ PORTA(RA0-RA3) خلال ترانزستورات التحكم نوع PNP .
• الشرائح السبعة A-G متصلة بالمنفذ PORTD (RD0-RD6) خلال مقاومات تحديد التيار .
• مفتاح ( حساس) التزايد متصل بالطرف RB0 ومفتاح التناقص متل بالطرف RB1 .

البرنامج الأول باستخدام 2 وحدة عرض أى أن مدى التزايد والتناقص هو 0-99 :

كود:
/*
UP Down Counter with two 7-Segment Display Multiplexing
In this project two common anode 7-segment LED displays are connected to
PORTD of a PIC16F877A  * 4MHz .
Digit 1 (left digit) enable pin is connected to port pin RA0 ( TENS)
and digit 2 (right digit) enable pin is connected to port pin RA1 (ONES) .
The program counts up -down from buttons at RB0 , RB1 .
The display is updated in a timer interrupt service routine at every 5ms by :
Reload TMR0=100 & prescaler ratio 1:32>> imer interrupt service routine at
 (255-100) *32us=5ms = scanning time
*/

#define TENS_DIG PORTA.F0 //tens unit
#define ONES_DIG PORTA.F1//ones unit

//Global variable
unsigned char Count = 0;
unsigned char Flag = 0;
bit oldstate1;
bit oldstate2;

//-Function to Return mask for common anode 7-seg. display
unsigned short mask(unsigned short num) {
 switch (num) {
 case 0 : return 0xC0;
 case 1 : return 0xF9;
 case 2 : return 0xA4;
 case 3 : return 0xB0;
 case 4 : return 0x99;
 case 5 : return 0x92;
 case 6 : return 0x82;
 case 7 : return 0xF8;
 case 8 : return 0x80;
 case 9 : return 0x90;
 } //case end
}


// TMR0 timer interrupt service routine. The program jumps to the ISR at every 5ms.
void interrupt ()
{

//Local variable
unsigned char TENS_SEG, ONES_SEG; 		// tens=  left unit &ones= right unit
TMR0 = 100; 				// Re-load TMR0>>255-100=155usx32(prescaler)=5ms
INTCON = 0x20; 				// >>>>Set T0IE and clear T0IF<<<<
Flag = ~ Flag; 				// Toggle Flag as switch
if(Flag == 0) 				// Do digit 1
{
ONES_DIG = 1;				// Disable digit 2
TENS_SEG = Count / 10; 			// TENS_SEG >>tens
PORTD = mask(TENS_SEG); 			// Send to PORTD
TENS_DIG = 0; 				// Enable digit 1>>RA0
}
else
{ // Do digit 2
TENS_DIG = 1; 				// Disable digit 1
ONES_SEG = Count % 10; 			// ONES_SEG >> ones
PORTD = mask(ONES_SEG); 			// Send to PORTD
ONES_DIG = 0; 				// Enable digit 2 >>RA1
}
}
//
// Start of MAIN Program. configure PORTA and PORTD as outputs.
// In addition, configure TMR0 to interrupt at every 5ms
//
void main()
{
ADCON1=0X07;        		//set A PORT general I/O
TRISD= 0; 			// PORTD are outputs
TRISA = 0; 			// RA0, RA1 are outputs
TENS_DIG = 1; 			// Disable digit 1
ONES_DIG = 1; 			// Disable digit 2
// Configure TMR0 timer interrupt
OPTION_REG = 0xC4;	 	// Prescaler = 32
TMR0 = 100; 			// Load TMR0L with 100
INTCON = 0xA0; 			// Enable TMR0 interrupt
//Delay_ms(1000);

for(;;) // Endless loop
{

//UP Count
if (Button(&PORTB, 0, 1, 0)) {               		// Button 0 : Detect logical 0
      oldstate1 = 1;                              		// Update flag
    }
    if (oldstate1 && Button(&PORTB, 0, 1, 1)) {   	// Detect zero-to-one transition
        Count = Count +1;
        oldstate1 = 0;                                                 	// Update flag
    }
//DOWN Count
        if(Button(&PORTB,1,1,0)){		// Button 1 : Detect logical 0
        oldstate2 = 1;                              		// Update flag
}

          if (oldstate2 && Button(&PORTB, 1, 1, 1)) {   	// Detect zero-to-one transition
            Count = Count -1;
            oldstate2 = 0;                              		// Update flag
}

    if (Count > 99)                 			// if it's more than 99 go to 0;
   Count = 0;

}
}

احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى ( أعجبته المشاركة )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 26-07-2017, 01:34 PM المشاركة 7   
افتراضي


البرنامج الثانى باستخدام 4 وحدة عرض أى أن مدى التزايد والتناقص هو 0-9999 :
الدائرة الكهربية :



البرنامج :

كود:
 
/*
UP Down Counter with Four 7-Segment Display Multiplexing
In this project four common anode 7-segment LED displays are connected to
PORTD of a PIC16F877A  * 4MHz .
Digit 1 (left digit) enable pin is connected to port pin RA0 ( Thousands)
and digit 2  enable pin is connected to port pin RA1 (Hundreds) .
and digit 3  enable pin is connected to port pin RA2 (Tens) .
and digit 4  enable pin is connected to port pin RA3 (Ones) .
The program counts up -down from buttons at RB0 , RB1 .
The display is updated in a timer interrupt service routine at every 5ms by :
Reload TMR0=100 & prescaler ration 1:32>> imer interrupt service routine at
 (255-100) *32us=5ms = scanning time
*/

#define Thous_Dig  PORTA.B0 //Thousands  unit
#define Hund_Dig  PORTA.B1//Hndreds unit
#define Tens_Dig PORTA.B2//Tens unit
#define Ones_Dig PORTA.B3//ones unit



//Global variable
unsigned char Count = 0;
unsigned char Flag = 0;
bit oldstate1;
bit oldstate2;

//-Function to Return mask for common anode 7-seg. display
unsigned short mask(unsigned short num) {
 switch (num) {
 case 0 : return 0xC0;
 case 1 : return 0xF9;
 case 2 : return 0xA4;
 case 3 : return 0xB0;
 case 4 : return 0x99;
 case 5 : return 0x92;
 case 6 : return 0x82;
 case 7 : return 0xF8;
 case 8 : return 0x80;
 case 9 : return 0x90;
 } //case end
}
// TMR0 timer interrupt service routine. The program jumps to the ISR at every 5ms.

void interrupt ()
{

//Local variable
unsigned char Thous_Seg,Hund_Seg,Tens_Seg, Ones_Seg;
TMR0 = 100; 				// Re-load TMR0>>255-100=155usx32(prescaler)=5ms
INTCON = 0x20; 				// >>>>Set T0IE and clear T0IF<<<<
if(Flag == 0) 				// Do digit 1
{
Ones_Dig = 1;
Tens_Dig = 1;
Hund_Dig = 1;
Thous_Seg = Count / 1000; 			// TENS_SEG >>tens
PORTD = mask(Thous_Seg); 			// Send to PORTD
Thous_Dig = 0; 				// Enable digit 1>>RA0
}
 else
if(Flag == 1) 				// Do digit 1
{
Ones_Dig = 1;
Tens_Dig = 1;
Thous_Dig = 1;

Hund_Seg = (Count / 100)%10; 			// TENS_SEG >>tens
PORTD = mask(hund_Seg); 			// Send to PORTD
Hund_Dig=0; 				// Enable digit 1>>RA0
}
else
if(Flag == 2) 				// Do digit 1
{
Ones_Dig = 1;
Hund_Dig = 1;
Thous_Dig = 1;
Tens_Seg = (Count / 10)%10; 			// TENS_SEG >>tens
PORTD = mask(Tens_Seg); 			// Send to PORTD
Tens_Dig=0; 				// Enable digit 1>>RA0
}

 else
if(Flag == 3) 				// Do digit 1
{
Tens_Dig = 1;
Hund_Dig = 1;
Thous_Dig = 1;

Ones_Seg = Count %10; 			// TENS_SEG >>tens
PORTD = mask(Ones_Seg); 			// Send to PORTD
Ones_Dig = 0; 				// Enable digit 1>>RA0
}

 Flag =Flag++;
if (Flag > 3)    Flag=0;

				// Toggle Flag as switch  , Counter


}
//
// Start of MAIN Program. configure PORTA and PORTD as outputs.
// In addition, configure TMR0 to interrupt at every 10ms
//
void main()
{
ADCON1=0X07;        		//set A PORT general I/O
TRISD= 0; 			// PORTD are outputs
PORTD=0XFF;
TRISA = 0; 			//  outputs
PORTA=0XFF;
TRISB=0XFF;
PORTB=0XFF;

// Configure TMR0 timer interrupt
OPTION_REG = 0xC4;	 	// Prescaler = 32
TMR0 = 100; 			// Load TMR0L with 100
INTCON = 0xA0; 			// Enable TMR0 interrupt

for(;;) // Endless loop
{

//UP Count
if (Button(&PORTB, 0, 1, 0)) {               		// Button 0 : Detect logical 0
      oldstate1 = 1;                              		// Update flag
    }
    if (oldstate1 && Button(&PORTB, 0, 1, 1)) {   	// Detect zero-to-one transition
        Count = Count +1;
        oldstate1 = 0;                                                 	// Update flag
    }
//DOWN Count
        if(Button(&PORTB,1,1,0)){		// Button 1 : Detect logical 0
        oldstate2 = 1;                              		// Update flag
}

          if (oldstate2 && Button(&PORTB, 1, 1, 1)) {   	// Detect zero-to-one transition
            Count = Count -1;
            oldstate2 = 0;                              		// Update flag
}

    if (Count > 9999)                 			// if it's more than 9999 go to 0;
   Count = 0;

}
}

احصائية الشكر والاعجاب - 2 شكراً, 0 عدم اعجاب, 2 اعجاب
شكراً عبدالله حجازى, سعيد قادر ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى, سعيد قادر ( أعجبته المشاركة )

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:333
قديم 28-07-2017, 12:28 PM المشاركة 8   
افتراضي


الموديول TIMER1 :
• الموديول Timer1 هو مؤقت / عداد 16-bit يتكون من سجلين 8-bit هما السجل TMR1H و السجل TMR1L ، وهى قابلة للقراءة منها والكتابة إليها .
• زوج سجلات المؤقت TMR1 تتزايد من 0000h إلى FFFFh وتلف إلى 0000h . مقاطعة المؤقت TMR1 ، إذا كانت ممكنة ، تتولد عند الطفحان overflow حيث يتم تحديد (1) بت علم المقاطعة TMR1IF (PIR1<0>) . هذه المقاطعة يمكن تمكينها / تعطيلها عن طريق تحديد (1) / مسح (0) بت تمكين المقاطعة
TMR1IE (PIE1<0>) .
المؤقت Timer1 يمكن أن يعمل فى نظامين :
• نظام المؤقت timer .
• نظام العداد counter .
يتم تحديد نظام الغمل عن طريق بت اختيار الساعة TMR1CS (T1CON<1>) .
فى نظام المؤقت ، يتزايد المؤقت Timer1 كل دورة تعليمة .
فى نظام العداد ، يتزايد عن كل حافة صاعدة لدخل الساعة الخارجية .
• يمكن تفعيل / تعطيل المؤقت Timer1 عن طريق تحديد (1) / مسح (0) بت التحكم
TMR1ON (T1CON<0>) .



[img] [/img]

عمل المؤقت Timer1 فى نظام المؤقت Timer :
يتم اختيار نظام المؤقت timer عن طريق مسح (0) البت TMR1CS (T1CON<1>) . فى هذا النظام ، يكون دخل الساعة إلى المؤقت هو Fosc/4 . بت النحكم فى التزامن T1SYNC (T1CON<2>) لا يكون لها تأثير لأن الساعة الداخلية تكون دائما متزامنة .
عمل المؤقت Timer1 كعداد Counter :
المؤقت Timer1 قد يعمل فى أى من النظام المتزامن أو الغير متزامن اعتمادا على تحديد البت TMR1CS .
عندما يتم تزايد المؤقت Timer1 من خلال مصدر خارجى ، يحدث التزايد عند الحافة الصاعدة . بعد تمكين المؤقت Timer1 فى نظام العداد يجب أن لدى الموديول أولا حافة هابطة قبل أن يبدأ الغداد فى التزايد .





صيغة حساب الزمن :

كود:
T  = machine cycle * prescaler * count (65536 - TMR1H: TMR1L);
Machine cycle = 4 / Fosc;
Fosc  is the crystal oscillator clock frequency
مثال : توليد زمن قدرة واحد ثانية باستخدام كريستال بتردد 20MHz .

كود:
Machine cycle = 4 / 20Mhz = 0.2us. T = 0.2 * 4 * 12500 = 10000us or 10ms.
سوف نستخدم المقاطعة للحصول على زمن واحد ثانية بعد 100 مرة مقاطعة .


كود:
Char count;
	
void  interrupt () { 
Count ++ ;       // for each TIMER1 interrupt increments the counting variable
TMR1L = 0x2C ;   // recharge the TMR1L;
TMR1H = 0xCF ;   // recharge the TMR1H;
PIR1.TMR1IF = 0 ;  // clear the overflow.
}
	
void  main () {
INTCON.GIE = 1 ; // enable global interruption;
INTCON.PEIE = 1 ; // enable interruption of peripherals;
PIE1.TMR1IE = 1 ; // enable interrupt of TIMER1;
// TMR1 receives the value 53036 (65536 - 12500), which in Hexadecimal is 0xCF2C
TMR1L = 0x2C ; // least significant byte
TMR1H = 0xCF ; // most significant byte
T1CON = 0b00100001 ; // Timer mode, prescaler 1: 4, internal clock;
while ( 1 ) {
if (count == 100 ) {     // when count = 100, that is, when time reaches
PORTB.RB0 = ~ PORTB.RB0 ; // 1s (100 * 10ms) reverses the state of portb, pin RB0.
}                     
	
}
}

احصائية الشكر والاعجاب - 1 شكراً, 0 عدم اعجاب, 1 اعجاب
شكراً عبدالله حجازى ( شكر العضو على هذه المشاركة )
اعجاب عبدالله حجازى ( أعجبته المشاركة )
إضافة رد

العلامات المرجعية

«     الموضوع السابق       الموضوع التالي    »
أدوات الموضوع

الانتقال السريع إلى


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

Powered by vBulletin® Version 3.8.6, Copyright ©2000 - 2025