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

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

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 08:46 PM المشاركة 1   
افتراضي شرح لبرنامج متعدد المهام باستخدام المقاطعة بالمؤقت Timer0 : وميض ليد وإخراج أصوات : Twitter FaceBook Google+



شرح لبرنامج متعدد المهام باستخدام المقاطعة بالمؤقت Timer0: وميض ليد وإخراج أصوات :
الخطوة الأولى : كتابة التعليقات :
سوف نستخدم طريقتى "التعليقات" :
· التعليق باستخدام الرمز "//" وهو يسمح لك بوضع تعليق فى سطر واحد فقط .

· أما التعليق الذى يحتاج إلى أكثر من سطر فنضع قبل بدايته الرمز "/* ونضع الرمز"*/" بعد نهايته.







كود:
//STEP 1 Comments /*Name : LED & SOUNDER PICMICRO : PIC16F877A */
الخطوة الثانية : التعريفات :

اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 08:58 PM المشاركة 2   
افتراضي


الخطوة الثانية : التعريفات :

نستخدم التوجيه #define لتعريف رموز أواسماء تسهل فهم وتتبع البرنامج , على سبيل المثال , عندما يجد المترجم كلمة TEMP_LED فسوف يستبدلها بالعدد 250 وهكذا لباقى الرموز .
الاسم TEMP_LED سجل يحفظ القيمة 250 وسوف يستخدم فى مقارنة حالة الليد كل 250 ملى ثانية , وباقى التعاريف نحتاجها لتعريف طرف توصيل الليد RD0 وطرف توصيل الجرس RD1 وأخيرا تعريف بت علم المقاطعة بالمؤقت Timer0 وهو T0IF باعتباره بدلا من الاسم الطويل INTCON.T0IF .

كود:
// STEP 2: 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"

الخطوة الثالثة : إعلان المتغيرات :

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

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 09:03 PM المشاركة 3   
افتراضي


الخطوة الثالثة : إعلان المتغيرات :
نعرف (نعلن عن) متغير ونسميه TimerLed كما نذكر أن هذا المتغير يجب أن يكون من نوع unsigned و char ( أى 8 بت ومن ثم فإن هذا المتغير يمكن أن يأخذ قيم أعداد صحيحة integer بين الصفر و 255) , أيضا نخصص له قيمة ابتدائية هى الصفر.
ملاحظة :
عندما تعلن عن متغير يجب دائما وضع التتابع التالى :

unsigned or signed / datatype / variable name / Any initialization / ;



كود:
// STEP 3 : 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 */

الخطوة الرابعة : وضع جميع الإعدادات فى دالة للمساعدة فى تبسيط البرنامج الرئيسى وتسهيل فهمه وتتبعه وتطويره :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 09:09 PM المشاركة 4   
افتراضي


الخطوة الرابعة : وضع جميع الإعدادات فى دالة للمساعدة فى تبسيط البرنامج الرئيسى وتسهيل فهمه وتتبعه وتطويره :
هذه الدالة (والتى سوف يتم استدعائها فيما بعد فى البرنامج الرئيسى ) , سوف نضمنها جميع خيارات الإعدادات لسجل الخيارات OPTION_REG وسجل التحكم فى المقاطعة INTCON بحيث نمكن المقاطعة بالمؤقت Timer0 مع تعيين prescaler بالقيمة 1:32 , بهذه الطريقة , وعن طريق بدء المؤقت Timer0 من القيمة 100 , نحصل ( بكريستال 20MHz ) بمقاطعة زمنية كل واحد ملى ثانية .
جسم الدالة يحتوى على :

كود:
//STEP 4 : Setting Function , Others 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 }

الخطوة الخامسة : الدالة الرئيسية :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 09:25 PM المشاركة 5   
افتراضي


الخطوة الخامسة : الدالة الرئيسية :
الآن إلى البرنامج الرئيسى :


كود:
//step 5 : main function 
void main ( )
 {

فى البداية يتم استدعاء دالة الإعدادات :


كود:
settings ( ) ; // Run Setting Function for ports and registers

بتنفيذ جميع التعليمات الموجودة بدالة الأعدادات يتم تحديد وتهيئة السجلات .
السطر التالى يبدأ "حلقة غير منتهية" , كما ترى هذه الحلقة لا تفعل شىء ولكنها تعمل على "تنفيذ التعليمات بصفة مستمرة " .


كود:
while ( 1 ) // run a loop {

يظل الجرس BUZZER فى حالة توصيل ON لمدة 200 ميكروثانية ثم يظل فى حالة فصل OFF لمدة 200 ملى ثانية أخرى ثم تتكرر العملية نتيجة وجود الحلقة الغير منتهية while(1) . نتيجة لذلك يظهر على الطرف RD1 , المتصل به الجرس , موجة مربعة بتردد 2.5KHz :
الزمن الدورى :
T= 200+200 = 400 s
والتردد :

F=1/T=2.5 KHz
كود:
/* 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

كما ترى , توليد موجة مربعة بسيط للغاية . ولكن إذا أردنا فى نفس الوقت (أثناء سماع الصوت) عمل شىء آخر ما ؟
الخطوة السادسة : روتين خدمة المقاطعة IRS


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 09:43 PM المشاركة 6   
افتراضي


الخطوة السادسة : روتين خدمة المقاطعة IRS
هنا يأتى دور "المقاطعة بالمؤقت Timer0" : بالإعدادات الموجودة بدالة الإعدادات ضمنا أنه كل واحد ملى ثانية يتم مقاطعة البرنامج الرئيسى لحظيا وتنفيذ التعليمات الموجودة بدالة المقاطعة (روتين خدمة المقاطعة)
كود:
// STEP 6 : 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?
       {

وحيث أن مصدر المقاطعة هو المؤقت Timer0 , فإن أول شىء نفعله هو وضع (تحميل) القيمة الابتدائية بالمؤقت Timer0 :


كود:
TMR0 = 100 ; // Timer0 reloaded


بعد ذلك نقوم بتزايد متغير عدادنا TimerLed(الذى تم إعلانه مسبقا) بوحدة واحدة ( المؤثر ++ يسمى تزايد بواحد ) :



كود:
TimerLed ++;  // Increment the timer for the blinking LED

الآن دعنا نتحقق (نختبر) عن طريق المقارنة باستخدام المؤثر "أكبر من أو تساوى >= " من أن قيمة عدادنا TimerLed قد تخطى 250 (تذكر أنه قد تم تعريف المتغير TEMP_LED بأنه يساوى 250 ) :
كود:
if( TimerLed >= TEMP_LED ) // If the time has passed TEMP_LED=250 {

إذا تحقق هذا الشرط , نقوم بعكس حالة الليد وتصفير المتغير :

كود:
LED = LED^1 ;  // Invert LED status to flash .
          TimerLed = 0 ;  // Reloading the LED timer to start again
          }

التأثير الذى تحصل عليه فى الاساس هو وميض ليد بفترة زمنية نصف ثانية ( 250 ملى ثانية توصيل ON و 250 ملى ثانية فصل OFF ) .
الآن دعنا نقوم بمسح clear بت علم المقاطعة بالمؤقت Timer0 وإلا فلن نحصل على علم مقاطعة مرة أخرى .
كود:
T0IF = 0 ;  // Reset the interrupt flag of timer 0
       }  // end that occurred on Timer0 interrupt
 }  // end of interrupt service routine
بانتهاء روتين خدمة المقاطعة يعود التحكم إلى البرنامج الرئيسى . حيث أن هذا التتابع للتعليمات ( اختبار الشرط , تزايد المؤقت , عكس حالة الليد .....) يأخذ عدد قليل من الميكروثوانى , فإن التأثير سوف يكون مشاهدة وميض الليد و سماع صوت الجرس : كما لو كانت المهمتان يتم إجراؤهما فى نفس الوقت ( فى الحقيقة يتم إجراؤهما فى أزمنة منفصلة ولكن بسرعة عالية جدا ).

كود البرنامج :


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,894
نشاط [ F.Abdelaziz ]
قوة السمعة:332
قديم 11-02-2012, 09:47 PM المشاركة 7   
افتراضي


كود البرنامج :



كود:
//STEP 1 Comments
/*Name : LED & SOUNDER
PICMICRO : PIC16F877A */
// STEP 2: 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"
// STEP 3 : 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 */
//STEP 4 : Setting Function , Others
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
 }
//step 5 : 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
// STEP 6 : 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^1 ;  // 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



khamed tabet
:: مهندس متميز ::
تاريخ التسجيل: Jul 2010
المشاركات: 333
نشاط [ khamed tabet ]
قوة السمعة:0
قديم 11-02-2012, 11:03 PM المشاركة 8   
افتراضي


براك الله فيك يا مهندس عبد العزيز على مجهودات
لكن عندما جربت البرنامج طلع لي الخطأ في PORTD

إضافة رد

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

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

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


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

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