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

   

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 30-04-2015, 03:19 PM المشاركة 33   
افتراضي المقاطعات : المقاطعة الخارجية عن طريق تطبيق نبضة على الطرف RB :



المقاطعات : المقاطعة الخارجية عن طريق تطبيق نبضة على الطرف RB :

سوف نستعرض هذا النوع من مصادر المقاطعة من خلال المثال التالى لبرنامج المقاطعة الخارجية  :
الدائرة الكهربية :







فى هذا البرنامج سوف نبين الإعدادات الأساسية للمقاطعة .
• المهمة الأصلية للبرنامج هى إنشاء عداد ثنائى تصاعدى (متزايد) على خرج المنفذ Port D  باستخدام العبارات output_d(x); x++;  .
• يتم مقاطعة هذه المهمة عند الضغط على المفتاح الضاغط المتصل بالطرف RB0 ليصبح الطرف RB0 (الخاص بالمقاطعة الخارجية) فى الحالة المنخفضة ، وفقا للعبارة ext_int_edge(H_TO_L); ، مما يجبر البرنامج على تنفيذ روتين خدمة المقاطعة الخارجية void isrext() ، والذى يتسبب فى إضاءة جميع الليدات output_d(255); لمدة ثانية واحدة delay_ms(1000); . ثم بعد ذلك يتم استئناف المهمة الأصلية تلقائيا من عند نقطة توقف التنفيذ .
• عندما يتم كشف مقاطعة الطرف RB0 خلال الحلقة الرئيسية ، يتم حفظ السياق ( محتويات السجل الحالى) قبل تنفيذ روتين خدمة المقاطعة .

البرنامج :


كود:
// External interrupt RB0 low interrupts output count
#include <16F877A.h>
#use delay(clock = 4000000)

#int_ext				 // Interrupt name
void isrext() 				// Interrupt service routine
{ 
output_D(255); 		// ISR action
delay_ms(1000);
}

void main() //*******************
{
int x;

enable_interrupts(int_ext); 		// Enable named interrupt
enable_interrupts(global); 		// Enable all interrupts
ext_int_edge(H_TO_L); 		// Interrupt signal polarity

while(TRUE)				 // loop
{
output_D(x); x++ ;
delay_ms(100);
}
}

اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 30-04-2015, 03:24 PM المشاركة 34   
افتراضي تطبيق على المقاطعة الخارجية : برنامج أضواء متحركة بنماذج متعددة :


تطبيق على المقاطعة الخارجية : برنامج أضواء متحركة بنماذج متعددة :



البرنامج :

كود:
#include <16F877A.h> 
#use delay(clock=4000000)

int8 mode,i; 
byte temp;

#INT_EXT 
EXT_ISR() { 
mode++; 
if (mode==9) mode = 0; 
} 
// End of INT

void program1(); 
void program2(); 
void program3(); 
void program4(); 
void program5(); 
void program6(); 
void program7(); 
void program8();

void main() { 
set_tris_d(0x00); 
set_tris_b(0xFF); 
output_d(0xff);

   enable_interrupts(int_EXT);
   enable_interrupts(GLOBAL);
   ext_int_edge(L_TO_H); 
 
mode = 0; 
while (TRUE) {
switch(mode) { 
case 1: program1(); break; 
case 2: program2(); break; 
case 3: program3(); break; 
case 4: program4(); break; 
case 5: program5(); break; 
case 6: program6(); break; 
case 7: program7(); break; 
case 8: program8(); break; 
} 
} 
} 
void program1() { 
output_d(0x00);
delay_ms(250); 
output_d(0xFF);
delay_ms(250); 
} 
void program2() { 
temp = 0xFF; 
for (i=0;i<=8;i++) { 
output_d(temp); 
delay_ms(250); 
temp >>= 1; 
} 
} 
void program3() { 
temp = 0xFF; 
for (i=0;i<=8;i++) { 
output_d(temp);
delay_ms(250); 
temp <<= 1; 
} 
} 
void program4() { 
output_d(0xAA); 
delay_ms(500); 
output_d(0x55); 
delay_ms(500); 
} 
void program5() { 
output_d(0x7E); 
delay_ms(150); 
output_d(0xBD); 
delay_ms(250); 
output_d(0xDB); 
delay_ms(150); 
output_d(0xE7); 
delay_ms(150);
output_d(0xDB); 
delay_ms(150); 
output_d(0xBD); 
delay_ms(150); 
output_d(0x7E); 
delay_ms(150); 
} 
void program6() { 
temp = 0xFF; 
for (i=0;i<=8;i++) { 
output_d(temp); 
delay_ms(250); 
temp = temp >> 1; 
} 
} 
void program7() { 
output_d(0xFE); 
delay_ms(150); 
output_d(0xFD); 
delay_ms(150); 
output_d(0xFB); 
delay_ms(150); 
output_d(0xF7); 
delay_ms(150); 
output_d(0xEF); 
delay_ms(150); 
output_d(0xDF); 
delay_ms(150); 
output_d(0xBF); 
delay_ms(150); 
output_d(0x7F); 
delay_ms(150); 
} 
void program8() { 
output_d(0x7F); 
delay_ms(150); 
output_d(0xBF); 
delay_ms(150); 
output_d(0xDF); 
delay_ms(150); 
output_d(0xEF); 
delay_ms(150); 
output_d(0xF7); 
delay_ms(150); 
output_d(0xFB); 
delay_ms(150); 
output_d(0xFD); 
delay_ms(150); 
output_d(0xFE);
delay_ms(150); 
}

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

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 30-04-2015, 05:03 PM المشاركة 35   
افتراضي مثال على المقاطعة الخارجية External interrupt : عداد تصاعدى


مثال على المقاطعة الخارجية External interrupt : عداد تصاعدى

تمهيد :
• الميكروكونترولر PIC16F877A يسمح بالمقاطعة الخارجية INT_EXT ، مصدر المقاطعة الخارجية ينبغى أن يوصل إلى الطرف RB0/INT .
• قبل تمكين المقاطعة الخارجية يجب تحديد نوع حافة الساعة الخارجية :
# حافة موجبة أى صاعدة ext_int_edge(L_TO_H)
# أو حافة سالبة أى هابطة ext_int_edge(H_TO_L)






فى هذا البرنامج سوف يتم توصيل ساعة خارجية على الطرف RB0 ، ويقوم البرنامج بعد النبضات وعرض قيم العداد عندما يتم الضغط على المفتاح الضاغط المتصل بالطرف RB1 .
البرنامج :

كود:
#include <16F877A.h> 
#use delay(clock=4000000)
#include<lcd.c>

long count = 0;          /* Global variable */

#INT_EXT          /* ISR for external "B0" interrupt */
void isr(){count++;}

void main() {

lcd_init();

ext_int_edge(L_TO_H); /* Interrupt on (+) edge */
enable_interrupts(INT_EXT); /* Enable interrupts */
enable_interrupts(GLOBAL);

while(TRUE){
if(input(pin_b1))   { /* When SW is depressed... */
printf(lcd_putc,"\fCounter = %lu",count); /* ...send it out! */
delay_ms(200); /* Wait 200 ms to debounce */
}
}
}


moon620
:: مهندس ::
تاريخ التسجيل: Apr 2015
المشاركات: 9
نشاط [ moon620 ]
قوة السمعة:
قديم 01-05-2015, 01:02 AM المشاركة 36   
افتراضي


شكرا على هذا الشرح الشامل


الصورة الرمزية Sallam
Sallam
:: مهندس متميز ::
تاريخ التسجيل: Mar 2006
الدولة: Syria
المشاركات: 515
نشاط [ Sallam ]
قوة السمعة:
قديم 01-05-2015, 01:12 AM المشاركة 37   
افتراضي


أشكرك أستاذي العزيز F.Abdelaziz

انا متابع معك حتى الوصول للغاية وهي فهم المعلومات وتطبيقها


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 01-05-2015, 04:47 PM المشاركة 38   
افتراضي المؤقتات والمقاطعة والميكروكونترولر PIC16F877A مع المترجم CCS C :


المؤقتات والمقاطعة والميكروكونترولر 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 .



http://fathallaabdelaziz.forumarabia.com/




الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 01-05-2015, 05:44 PM المشاركة 39   
افتراضي برنامج مولد نبضات نبضة كل واحد ثانية :


برنامج مولد نبضات نبضة كل واحد ثانية :

كود:
/******************************************************
      Timer0-1 application with PIC16F877 
     *******************************************************/
#include <16f877.h>     // 
#use delay (clock=4000000) // 

int i=0; //

//****************** Timer0 interrupt ********************
#int_timer0  // Timer0 interrupt
void  timer0_isr ()   // Interrupt function name
{
    set_timer0(60);  	 // Put initial value in TMR0 register
//256 * (256 – 60) = 50176 us 

    i++;  		 //i value is increased by 1 
    if (i==10)  		// if i = 10 , led on  t = 10 * 50176 = ~0.5 sec
       output_high(pin_b0);
    
    if (i==20)  		// if i = 20 ,t=1s, led off , and reset counter
       {
          output_low(pin_b0);
          i=0;
       }
}

/********* main function ********/

void main ( )
{
   
   set_tris_b(0x00);   // 
   output_b(0x00);     // 

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256); // 
   set_timer0(60);   // 
   enable_interrupts(INT_timer0); // 
   enable_interrupts(GLOBAL);     // 

   while(1);   // 

 }



الصورة الرمزية Sallam
Sallam
:: مهندس متميز ::
تاريخ التسجيل: Mar 2006
الدولة: Syria
المشاركات: 515
نشاط [ Sallam ]
قوة السمعة:
قديم 01-05-2015, 08:06 PM المشاركة 40   
افتراضي



اتخاذ القرار Decision Making


كود:
//Lesson1-EX4 Tests an input
#include <16F877A.h>
void main()
{
   int x; 					// Declare variable
   output_D(0); 				// Clear all outputs

  while(1) 					// Loop always
    {
         x = input(PIN_C0); 			// Get input state
        if(x == 1)output_high(PIN_D0); 	// Change output
   }
}



.

أستاذي العزيز في هذا المثال لماذا لا يتكرر البرنامج عند كل ضغط للمفتاح
فإنه يظهر قيمة D0=1 ولا يتغير شيء فيما بعد

وأيضا المثال الذي يليه نفس الشي وعند استخدام حلقة FOR
يتم تنفيذ الأمر لمرة واحدة فقط وحتى لو تكرر الضغط

أرجو توضيح هذه النقاط

أقوم بتطبيق المثال في المترجم وتجربته في بروتوس


مع كل الشكر وبالتوفيق



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