ما هو الميكروكونترولر Microcontroller ؟

صفحة 4 من اصل 4 الصفحة السابقة  1, 2, 3, 4

استعرض الموضوع السابق استعرض الموضوع التالي اذهب الى الأسفل

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 16, 2017 6:28 pm

أجهزة إستشعار المسافة Distance sensors :



تستخدم أجهزة إستشعار المسافة فى قياس طول المسافة من مكان نقطة موقع الجسم العائق obstacle إلى موقع المستشعر (الحساس) . تنفيذ هذا النوع من الأجهزة مفيد فى أنظمة التحكم وفى مشاريع الروبوتات robotics.
وكحالة محددة فأنه فى هذا الجزء سوف يتم العمل بالحساس GP2D12 (الموجود ضمن برنامج إيزيس) ، هذا الحساس يستخدم تقنية إرسال الشعاع الضوئى للأشعة تحت الحمراء واستقبال إنعكاسها لتحديد المسافة . الشكل التالى يبين المظهر الطبيعى ، والأطراف ، والرمز فى برنامج إيزيس لهذا الحساس :




مثل هذا الحساس له سلوك غير خطى nonlinear ، هذا يعنى أن الخرج ليس له دالة تحويل خطية . لفهم هذا المفهوم بوضوح الرسم البيانى التالى يبين سلوك الخرج كدالة فى المسافة :



سلوك مثل هذا الحساس صعب التنفيذ ، لأنه فى بعض الحالات لا يقدم المصنع دالة تحويل مفيدة حتى يمكن استخدامها فى شكل معادلة واحدة . وعلى الرغم من ذلك فهذا لا يشكل عقبة أمام استخدام الحساس . كما هو موضح فى الداتا شيت أن المدى المؤثر من 10 إلى 80 سنتيمتر ( Effective Range: 10 to 80 cm) كما هو مبين فى الرسم البيانى .
الرسم البيانى الموضح موجود بالداتا شيت الخاص بالجهاز ويتم تنفيذه تجريبيا (نتيجة تجارب) . لوصف سلوك الحساس والحصول على دالة التحويل من الضرورى إجراء عملية رياضية تعرف باسم "الخطية" linearization . لتحقيق هذه الغاية يتم إجراء عملية "إستيفاء" interpolation بعدد معروف من نقاط الدالة ، هذه النقاط تؤخد من القياسات التجريبية . كلما زاد عدد النقاط كلما زادت دقة تقييم دالة التحويل .
لبدء هذه العملية يتم اختيار نقطتين موزعين بالتساوى . على سبيل المثال النقطة عند مسافة 10cm والنقطة عند مسافة 80cm . لكل نقطة نكون معادلة فيكون لدينا معادلتين من الدرجة الأولى فى هذه الحالة ، حيث يتم حلهما معا وإيجاد الثوابت .
لفهم هذا المفهوم ، نفترض أن المغير المستقل x يعبر عن جهد خرج الحساس بالفولت والمتغير التابع y يعبر عن المسافة بالسنتيمتر ونعتبر أن المعادلة التالية تعبر عن سلوك الحساس :



باعتبار أن y تمثل المسافة و x تمثل جهد خرج الحساس المستخدم ومن الرسم البيانى التجريبى نحصل على :



عندئذ يمكن كتابة المعادلات :

https://i11.servimg.com/u/f11/18/74/92/45/1113.jpg

ونستطيع تكوين معادلتين فى مجهولين كما يلى :



بحل المعادلين يمكن تعيين الثوابت كما يلى :

https://i11.servimg.com/u/f11/18/74/92/45/1311.jpg

بهذه الطريقة يمكن وضع صيغة لدالة التحويل للحساس كما يلى :



وحيث أن المتغير x يمثل جهد خرج الحساس مع الوضع فى الاعتبار أنه لا يزيد عن 2.5 volts ، فيجب ضبط جهد المرجع للمحول من تناظرى لرقمى عند 2.5 volts . لتحديد التحويل يتم استخدام المعادلة :



بالتعويض نحصل على صيغة دالة التحويل التالية :



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

الكود:
// 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
//Variables Declaration  .
    unsigned int Radc, DisI;
    float Dis;
    char Text[16];

void main( void )
{
   
    //Set the ADC module with pin AN3
    //as positive reference voltage.
    ADCON1 = 0b11000001;
    //Initiation LCD
    Lcd_Init();
    //Clearing the cursor.
    Lcd_Cmd(_LCD_CURSOR_OFF);
    //Printing text.
    Lcd_Out( 1, 1, "Distance:");
   
    while(1) //Infinite Loop.
    {
              //Reading analog channel 0 .
              Radc=ADC_Read(0);
              //Implementation of the transfer function Equation
              Dis = (14226.02784/Radc)-4.793814433;
              //force the result to an integer value.
              DisI=Dis;
              //convert the integer value to string.
              IntToStr( DisI, Text );
              //Print the sensor reading.
              Lcd_Out( 2, 1, Text );
              //Delay 100m-seconds.
              delay_ms(100);
    }
}


وأخيرا للتحقق من سلوك النظام يتم التنفيذ ببرنامج إيزيس بالأجهزة التالية :
16F877A, RES, LM016L, GP2D12 وتكوين الدائرة الكهربية كما فى الشكل التالى :










Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 16, 2017 8:23 pm

أجهزة الأستشعار LDR Sensors
أجهزة الاستشعار LDR هى أجهزة تتغير مقاومتها اعتمادا على شدة الضوء ، كلما ارتفعت شدة الضوء انخفضت مقاومة LDR .
هذه الأجهزة مفيدة لتحديد وجود أو غياب الإضاءة المحيطة ، لذلك فهى تستخدم فى الأنظمة التى تتطلب التحكم فى شدة الإضاءة .
الشكل التالى يبين المظهر الطبيعى والرموز فى برنامج إيزيس :




الخصائص الكهربائية لهذه الأجهزة ليست صعبة التحقيق ، حيث أنها تعمل بطريقة بسيطة ويوجد لها مجموعة متنوعة من شركات التصنيع ، أجهزة LDR أو المقاومة الضوئية متوفرة تجاريا بمختلف الأحجام ، وهذا يعنى أن مدى التغير فى المقاومة يعتمد على الحجم ، فالحجم الكبير يكون له مدى صغير والعكس بالنسبة للحجم الصغير . قد يكون التغيرفى المقاومة ليس متماثلا فى اثنين من LDR لهما نفس الحجم . هذه الأسباب تجعلها سهلة الاستخدام لقراءة المقاومة أو الجهد بين طرفيها . أبسط طريقة لاستخدام LDR هى عمل مقسم جهد مع مقاومة ثابتة .
لفهم هذا المفهوم يمكنك النظر إلى الشكل التالى :



بتطبيق النظرية الأساسية لتقسيم الجهد على الدائرة السابقة نحصل على :

الكود:
Vout = Vcc * (LDR / (LDR+R))

من هذه المعادلة يمكن الحصول على المعادلة :

الكود:
LDR = (Vout)(R) / (Vcc – Vout) 

وحيث أن الجهد التناظرى بالقيمة Vout يدخل إلى المحول من التناظرى لرقمى ، وهو ما يعتبره الميكروكونترولر جهد دخل Vadc ، وباستخدام جهد المرجع الموجب بالقيمة 5 volts (الافتراضى) فإنه يمكن التعبير عن التحويل بالصيغة التالية :

الكود:
Vadc = Radc * (5 / 1023) = Radc * 0.004887585

بالتعويض فى المعادلة السابقة وبفرض أن الجهد Vccيساوى 5 volts يمكننا الحصول على العلاقة :

الكود:
LDR = (Radc)( 0.004887585) (R) / (5 – (Radc)( 0.004887585))

فى هذه الحالة الخاصة للتدريب على المحاكاة سوف نستخدم مقاومة مقسم الجهد بالقيمة 10k وبالتالى سوف تصبح معادلة LDR بالصيغة :

الكود:
 LDR = (Radc) (48.87585) / (5 – (Radc)( 0.004887585))


لإدراك المفاهيم السابقة يتم تحرير وترجمة ومراقبة وتحليل كودالمصدر للبرنامج التالى :

الكود:
// 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

//Dariables Declaration  .
    unsigned long Radc, DisI;
    char Text[16];

void main( void )
{
   
    //Initiation LCD
    Lcd_Init();
    //Cursor OFF.
    Lcd_Cmd(_LCD_CURSOR_OFF);
    //Printing text.
    Lcd_Out( 1, 1, "Resistance:");
   
    while(1) //Infinite Loop.
    {
              //Reading analog channel 0.
              Radc=ADC_Read(0);
              //Implementation the calculation of the LDR equation
              DisI = (Radc*48.87585533)/(5.0-Radc*0.004887585);
              //Convert the long integer value in string.
              LongToStr( DisI, Text );
              //Print the sensor reading.
              Lcd_Out( 2, 1, Text );
              //Delay 100m-seconds.
              delay_ms(100);
    }
}

للمحاكاة ببرنامج إيزيس يتم جلب الأجهزة التالية :
16F877A, RES, LM016L, TORCH_LDR وإنشاء الدائرة الكهربية الآتية :




Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الإثنين يوليو 17, 2017 9:34 am

أجهزة استشعار الضغط Pressure sensors :
الضغط هو متغير طبيعى، يمثل بمتجه يعرف بأنه القوة الواقعة على مساحة معينة . يتم الدلالة على الضغط بوحدات مختلفة تبعا لنظام الوحدات المستخدم ، فيمكن أن يعطى الضغط بالوحدات :
psi, Pascal, atmospheres, inches of mercury الخ.
للأغراض العملية لهذا الجزء سوف يتم العمل بحساس الضغط MPX4115 . خواص هذا الحساس تعطى بالكيلوباسكال Kilo Pascal ويمكنه قياس الضغوط فى المدى بين 15 kPa و  115 kPa، أو بين 2.18 psi  و 16.7 psi.
المظهر الطبيعى وتوزيع الأطرف ومز المحاكاة فى برنامج إيزيس موضح بالشكل التالى :




يتم التنفيذ تبعا لنوع الحساس ، كل حساس يجب أن يكون له "دالة تحويل" transfer function وهى العلاقة بين الخرج والدخل ، فى حالة حساس الضغط MPX4115 تتحدد دالة التحويل بواسطة الصناع بالعلاقة :

الكود:
Vout = Vs ( 0.009P – 0.095)  


حيث Vout هو جهد خرج الحساس ، و P هو الضغط بالكيلوباسكال Kilo Pascal ، و Vs جهد تغذية الحساس . من هذه المعادلة يمكن الحصول على صيغة للضغط بالشكل التالى :

الكود:
P = (111.111 Vout / Vs) + 10.555

عندما يتم إعداد الميكروكونترولر PIC ليعمل المحول من تناظرى لرقمىADC بدقة  10 بتات 10-bit يمكن استنتاج العلاقة التالية :

الكود:
Vadc = Radc * (5 / 1023)  

هذا الجهد هو نفسه جهد خرج الحساس ، بالتعويض عن Vout يمكن الحصول على المعادلة أو العلاقة التى يم استخدامها بالميكروكونترولر لقراءة الحساس ،  هذه العلاقة تكون بالشكل التالى :

الكود:
P = (0.54306 Radc / Vs ) + 10.555

هنا ، فى حالتنا الخاصة ، سوف يتم استخدام جهد التغذية بقيمة 5 volts وهو الذى يغذى الميكروكونترولر والحساس ولذلك فإن Vs تساوى 5 volts , ونحصل على العلاقة النهائية لنسبة التحويل بالصيغة التالية :

الكود:
P = 0.10861Radc +10.555

لاستعراض العمل الفعلى لمثل هذا الحساس راقب وحلل كود المصدر للبرنامج التالى :


الكود:

// 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
//Variables Declaration  .
 unsigned int Radc, PreI;
 float Pre;
 char Text[16];

void main( void )
{
 
 //LCD initiation.
 Lcd_Init();
 //Clearing the cursor.
 Lcd_Cmd(_LCD_CURSOR_OFF);
 //Printing text
 Lcd_Out( 1, 1, "Pressure in KPa:");
 while(1) //Infinite Loop.
 {
 //Reading ADC channel 0.
 Radc = ADC_Read(0);
 //Using the equation
 Pre = 0.10861*Radc+10,5555;
 //Forces the result to the integer part.
 PreI = Pre;
 //Converts the integer to a string.
 IntToStr( PreI, Text );
 //prints the result.
 Lcd_Out( 2, 1, Text);
 //Delay 100 m seconds.
 delay_ms(100);
 }
}

بعد تحرير وترجمة البرنامج , يمكن تنفيذ المحاكاة ببرنامج إيزيس بجلب الأجهزة الآتية :
16F877A, MPX4115, LM016L وتكون الدائرة الكهربية كما فى الشكل التالى :


Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الإثنين يوليو 17, 2017 12:38 pm

قياس درجة حرارة موجبة وسالبة باستخدام الحساس LM35
الدائرة الكهربية :
برجاء مراجعة الداتا شيت الخاصة بالحساس LM35



البرنامج :

الكود:

//program Thermometer_with_LM35 + & -

// 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

unsigned temp;      // unsigned (int)  0 .. 65535
unsigned tempn;
short tempout ;       //(signed) short (int)  - 128 .. 127
char Tc[5];

void main(){

TRISA  = 0xFF;  // designate PORTA as input
TRISB  = 0; //  as outputs

  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);              // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,1,"ENG.F.ABDELAZIZ");                // Write text in first row
  Lcd_Out(2,1,"WELCOME");                // Write text in second row
  Delay_ms(2000);
  Lcd_Cmd(_LCD_CLEAR);              // Clear display
  Lcd_Out(1,1,"ROOM TEMP.");                // Write text in first row
  while (1) {
      temp = ADC_read(0);
      tempn = ADC_read(1);
      temp = temp/2.046; // T = (Vadc mV /10) = (1/10) * ADC_READ*(5000/1023)
      tempn = tempn/2.046;
      tempout = temp - tempn;
      shortToStr(tempout,Tc);
      Lcd_Out(2,1,Tc);
    Lcd_Chr_Cp(223); // ASCII degree character
    Lcd_Chr_Cp('C');
    delay_ms(1000);
  }
}
 

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الإثنين يوليو 17, 2017 6:40 pm

مشروع : تصميم نظام قياس درجة الحرارة يعتمد على الميكروكونترولر باستخدام مقاومة حرارية RTD نوع Pt100 .



حساس الحرارة المستخدم له معامل حرارى =0.00385 α . وخواصه :



إذا فرضنا أن مقومة المصدر Rs=1K وجهد المصدر Vs=5V فإن الجهد بين طرفى الحساس RTD عند كل من نهايتى مدى درجة حرارة التشغيل تكون :



فإذا استخدمنا مكبر عمليات كسبه (تكبيرة) يساوى 5 فإن المدى الذى يرى من جهة المحول A/D سوف يكون:



وحيث أن المحول ذات 10 بت ومداه الكامل هو 5V فإن دقته أو الجهد المناظر لكل بت يكون :




ولكن مدى جهد الدخل :



ومن ثم سوف تكون دقة (حساسية) النظام حوالى واحد درجة مئوية .

المخطط الصندوقى :




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




مبدأ العمل :
• يتم تحويل الجهد بين طرفى الحساس RTD إلى الشكل الرقمى .
• يتم حساب مقاومة الحساس Rt باستخدام المعادلة :



• حيث Vt الجهد بين طرفى الحساس و Vs=5V و Rs=1k , بالتعويض نحصل على :



• يتم حساب درجة الحرارة من المعادلة :



• حيث t هى درجة الحرارة المقاسة بالدرجات المئوية ، و Rt هى مقاومة الحساس عند درجة الحرارة t ، و :



بالتعويض نحصل على :



حيث يمكننا حساب درجة الحرارة t بمعلومية المقاومة Rt .

البرنامج :
ملخص لخطوات البرنامج :
• إعدادات وحدة العرض .
• إعدادات الميكروكونترولر .
• إنشاء حلقة غير منتهية وفيها يتم :
# قراءة الجهد التناظرى بين طرفى الحساس RTD وتحويله إلى الشكل الرقمى .
# حساب المقاومة Rt .
# حساب درجة الحرارة t .
# عمل المقياس اللازم للتحويل إلى درجة حرارة .
# عرض درجة الحرارة على وحدة العرض LCD .
# الانتظار لثانية ثم التكرار بصفة مستمرة لتحديث البيانات .


الكود:
/* This project measures the temperature with a RTD PT100  and
* then displays on a LCD
Eng.F.Abdelaziz
 */

// LCD module connections
sbit LCD_RS at RC0_bit;
sbit LCD_EN at RC1_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_RS_Direction at TRISC0_bit;
sbit LCD_EN_Direction at TRISC1_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
// End LCD module connections

float rtdv,rtdr,temp,y; //  Floating-point Types
int msd, isd;
char temperature [6] ;

void main()
{

/* Initialize the microcontroller */

TRISA=0xFF;   //configure PORTA as Input direction
TRISB=0;      //configure PORTB as Output direction
TRISC=0;      //configure PORTD as Output direction
PORTA=0;   //Clear
PORTB=0;
PORTC=0;
//===============================================

  Lcd_Init();                              // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                 // CLEAR display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off

  Lcd_Out(1,1,"RTD Pt100 TEMP.");

while(1) {



rtdv = ADC_Read(0);// Get RTD voltage 10-bit result

rtdv  = rtdv  *5 /1024 ; //Scale RTD voltage in Volts
rtdv  = rtdv/5; //for op amp gain

/* Calculate RTD resistance rtdr */
rtdr = rtdv*1000.0/(5.0-rtdv);

/* Calculate temperature temp */

y = 0.15274- (rtdr-100.0)*0.0002310;
if(y>= 0) y = sqrt(y) ;
temp = (y-0.39083)/(-0.0001155) ;

ByteToStr(temp,temperature); // Change to string
  Lcd_Out(2,6,temperature); // Display
  Lcd_Chr(2, 9, 223);// Add degree character
  Lcd_Chr(2, 10, 'C');// Add letter "c"
delay_ms(1000);
//==============
}

}


النتائج :








Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الإثنين يوليو 17, 2017 7:24 pm

التدريب الرابع :
قياس درجة حرارة باستخدام الحساس LM35 وعرضها على 4 وحدات سفن سيجمنت

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










البرنامج :



الكود:

/*
 * Project name: Multiplexing_7-Segment 4 UNITS
     MCU:             PIC16F877A , ADC , LM35
     Oscillator:      HS, 8.0000 MHz
     SW:              mikroC PRO
*/
#define Digit1 PORTD.B0 // THOUTHAND
#define Digit2 PORTD.B1 // HUNDRED
#define Digit3 PORTD.B2 // TENS
#define Digit4 PORTD.B3 // ONES

unsigned char Display (unsigned char digit)
  {
    unsigned char pattern;
    unsigned char  SEGMENT_MAP[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
    pattern =  SEGMENT_MAP[digit] ;  //The pattern to return
    return (pattern);
  }

void main() {
  unsigned char DD1,DD2, DD3,DD4 ;
  unsigned int result; //
  float scale ;
  char num ;
  ADCON1= 0;           //
  TRISA.B0=1; // AN0 INPUT
  TRISD = 0;            // Configure PORTD as outputs , COMMON CATHODES
  TRISB = 0;            // Configure PORTB as outputs ,7 SEGMENT DATA PORT

Digit1 = 0;            //Disable digit 1
Digit2 = 0;            //Disable digit 2
Digit3 = 0;            //Disable digit 3
Digit4 = 0;            //Disable digit 4


  while(1){
  result=ADC_Read(0);  // Read analog value from channel 0
  scale = result * (5000.0/1023.0); // input analog voltage
  scale = scale /10.0 ; // input temp inc for LM35
  num = scale ;
 ///////////
       DD1 = num / 1000;       //Extract DD1 from result >>THOUTHAND
       PORTB = Display(DD1);    //Display the DD1
       Digit1 = 1;             //Enable digit 1
       Delay_Ms(10);            //a short 10ms delay
       Digit1 = 0;             //Disable digit 1
 /////////
       DD2 = (num/100) % 10;        // DD2 digit >>>HUNDRED
       PORTB = Display(DD2);    //Display the DD3
       Digit2 = 1;             //Enable digit 2
       Delay_Ms(10);            //a short 10ms delay
       Digit2 = 0;             //Disable digit 2
   ////////////
   DD3 = (num/10) % 10;       //Extract DD3 from result >>TENS
       PORTB = Display(DD3);    //Display the DD3
       Digit3 = 1;             //Enable digit 3
       Delay_Ms(10);            //a short 10ms delay
       Digit3 = 0;             //Disable digit 3
   /////////
   DD4 = num % 10;       //Extract DD4 from result >>ONES
       PORTB = Display(DD4);    //Display the DD4
       Digit4 = 1;             //Enable digit 4
       Delay_Ms(10);            //a short 10ms delay
       Digit4 = 0;             //Disable digit 4
    }
}

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الإثنين يوليو 17, 2017 7:30 pm



تطوير للتدريب السابق بوضع حرف :"C" للإشارة إلى الدرجات المئوية .

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



البرنامج :



الكود:

/*
 * Project name: Multiplexing_7-Segment 4 UNITS
     MCU:             PIC16F877A , ADC , LM35 MOD
     Oscillator:      HS, 8.0000 MHz
     SW:              mikroC PRO
*/
#define Digit1 PORTD.B0 //  DIGIT 1 FROM LEFT , THOUTHAND
#define Digit2 PORTD.B1 // DIGIT 2 FROM LEFT , HUNDRED
#define Digit3 PORTD.B2 // DIGIT 3 FROM LEFT , TENS
#define Digit4 PORTD.B3 // DIGIT 4 FROM LEFT ,  ONES

unsigned char Display (unsigned char digit)
  {
    unsigned char pattern;
    unsigned char  SEGMENT_MAP[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
    pattern =  SEGMENT_MAP[digit] ;  //The pattern to return
    return (pattern);
  }

void main() {
  unsigned char DD1,DD2, DD3,DD4 ;
  unsigned int ADC_result; //
  float scale ;
  unsigned int num ;
  ADCON1= 0;           //
  TRISA.B0=1; // AN0 INPUT
  TRISD = 0;            // Configure PORTD as outputs , COMMON CATHODES
  TRISB = 0;            // Configure PORTB as outputs ,7 SEGMENT DATA PORT

Digit1 = 0;            //Disable digit 1
Digit2 = 0;            //Disable digit 2
Digit3 = 0;            //Disable digit 3
Digit4 = 0;            //Disable digit 4


  while(1){
  ADC_result=ADC_Read(0);  // Read analog value from channel 0
  scale = ADC_result * (5000.0/1023.0); // input analog voltage
  num = scale /10.0 ; // input temp inc for LM35
 ///////////
       DD1 = num / 100;       //Extract DD1 from ADC_result >>THOUTHAND
       PORTB = Display(DD1);    //Display the DD1
       Digit1 = 1;             //Enable digit 1
       Delay_Ms(10);            //a short 10ms delay
       Digit1 = 0;             //Disable digit 1
 /////////
       DD2 = (num/10) % 10;        // DD2 digit >>>HUNDRED
       PORTB = Display(DD2);    //Display the DD3
       Digit2 = 1;             //Enable digit 2
       Delay_Ms(10);            //a short 10ms delay
       Digit2 = 0;             //Disable digit 2
   ////////////
   DD3 = num % 10;       //Extract DD3 from ADC_result >>TENS
       PORTB = Display(DD3);    //Display the DD3
       Digit3 = 1;             //Enable digit 3
       Delay_Ms(10);            //a short 10ms delay
       Digit3 = 0;             //Disable digit 3
   /////////
   //DD4 = num % 10;       //Extract DD4 from ADC_result >>ONES
       PORTB = 0x39;    //Display C CHARACTER
       Digit4 = 1;             //Enable digit 4
       Delay_Ms(10);            //a short 10ms delay
       Digit4 = 0;             //Disable digit 4
    }
}

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الإثنين يوليو 17, 2017 7:33 pm

[SIZE="4"]

إزالة حرف "C" واستخدام خانة الآحاد لبيان كسر الآحاد مع عرض النقطة العشرية على وحدة السفن سيجمنت :

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




البرنامج :



الكود:

/*
 * Project name: Multiplexing_7-Segment 4 UNITS
     MCU:             PIC16F877A , ADC , LM35 MOD
     Oscillator:      HS, 8.0000 MHz
     SW:              mikroC PRO
*/
#define Digit1 PORTD.B0 //  DIGIT 1 FROM LEFT , THOUTHAND
#define Digit2 PORTD.B1 // DIGIT 2 FROM LEFT , HUNDRED
#define Digit3 PORTD.B2 // DIGIT 3 FROM LEFT , TENS
#define Digit4 PORTD.B3 // DIGIT 4 FROM LEFT ,  ONES

unsigned char Display (unsigned char digit)
  {
    unsigned char pattern;
    unsigned char  SEGMENT_MAP[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
    pattern =  SEGMENT_MAP[digit] ;  //The pattern to return
    return (pattern);
  }

void main() {
unsigned char DD1,DD2, DD3,DD4 ;

float result; //
unsigned int result1;
  ADCON1= 0;           //
  TRISA.B0=1; // AN0 INPUT
  TRISD = 0;            // Configure PORTD as outputs , COMMON CATHODES
  TRISB = 0;            // Configure PORTB as outputs ,7 SEGMENT DATA PORT

Digit1 = 0;            //Disable digit 1
Digit2 = 0;            //Disable digit 2
Digit3 = 0;            //Disable digit 3
Digit4 = 0;            //Disable digit 4


  while(1){
  result=ADC_Read(0);  // Read analog value from channel 0 ,0 to 1023
  result = result * (5000.0/1023.0); // input analog voltage
  result = result /10.0 ; // input temp in C for LM35 0.0 to 150.0
   ///////////
 result = result *10.0 ; // float 0.0 to 1500.0
 result1=result; //integer 0 to 1500 to get fraction
 /////////////
       DD1 = result1 / 1000;       //Extract DD1 from result >>THOUTHAND(hundred)
       PORTB = Display(DD1);    //Display the DD1
       Digit1 = 1;             //Enable digit 1
       Delay_Ms(10);            //a short 10ms delay
       Digit1 = 0;             //Disable digit 1
 /////////
       DD2 = (result1/100) % 10;        // DD2 digit >>>HUNDRED (tens)
       PORTB = Display(DD2);    //Display the DD3
       Digit2 = 1;             //Enable digit 2
       Delay_Ms(10);            //a short 10ms delay
       Digit2 = 0;             //Disable digit 2
   ////////////
   DD3 = (result1/10) % 10;       //Extract DD3 from result >>TENS (ones)
       PORTB = Display(DD3);    //Display the DD3
       Digit3 = 1;             //Enable digit 3
       Delay_Ms(10);            //a short 10ms delay
       Digit3 = 0;             //Disable digit 3
   /////////
   DD4 = result1 % 10;       //Extract DD4 from result >>ONES(fraction)
       //PORTB = 0x39;    //Display C CHARACTER
   PORTB = Display(DD4);
       Digit4 = 1;             //Enable digit 4
       Delay_Ms(10);            //a short 10ms delay
       Digit4 = 0;             //Disable digit 4
    }
}
[/SIZE]

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الثلاثاء يوليو 18, 2017 6:25 pm

فكرة إنشاء ثرموستات باستخدام المقاومة السالبة NTC والمحول ADC ووحدة العرض LCD مع المترجم ميكرو سى
المقاومة السالبة المستخدم من النوع NTC / NTSA0WB203 وهذا النوع موجود فى برنامج ISIS .
هذه المقاومة لها معامل أو ثابت يسمى بيتا “β = 4050” ، ولها مقاومة قيمتها 20 كيلوأوم عند درجة حرارة 25 درجة مئوية .

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



يتم تشكيل مقسم جهد من مصدر جهد (بطارية ، على سبيل المثال ) والمقاومة السالبة NTC ومقاومة ثابتة R1 بقية 10 كيلوأوم ، وحساب درجة الحرارة من المعادلات التالية :



الكود:
VT=VB * RT/R1+RT
VB*RT = VT*R1 + VT * RT
VT*R1= RT(VB-VT)
RT = VT*R1/(VB-VT) = 10000VT/(5-VT) 


البرنامج :

الكود:

// 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
float tv,tr,temp,y;                //Equation variables
  unsigned unsigned int value;
  int Tc ;
  char text [7] ;

void main() {

  lcd_init();
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Cmd(_LCD_CURSOR_OFF);
  Lcd_Out(1,1,"ADC NTC TEMP." );
  while (1) {
      value = ADC_Read(0);

      tv = 5.0 * value / 1023.0;

      tr = tv * 10000.0 / (5.0 - tv);

      y = log(tr/20000.0);
      y = (1.0/298.15) + (y *(1.0/4050.0));

      temp=1.0/y;
      temp = temp -273.15;
     Tc = temp ;
     IntToStr(Tc , text);
     Lcd_Out(2,1,text);
          Lcd_Chr_Cp(223);
     Lcd_Chr_Cp('C');

  }
}
 

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 23, 2017 10:01 pm

فهم المقاطعات في الميكروكنترولر PIC مع المترجم ميكروسى برو :
المقاطعات هي مفهوم قوي في الأنظمة المدمجة من أجل التحكم فى الأحداث التى تقع في بيئة حساسة للوقت . في النظام المدمج النموذجي ، المعالج المدمج (الميكروكونترولر) هو المسؤول عن القيام بأكثر من مهمة واحدة (ولكن يمكن أن يقوم بعمل مهمة واحدة فقط في نفس الوقت ). على سبيل المثال ، دعونا نقول أنه في منظم درجة حرارة (ثرموستات) رقمى مبرمج لغرفة ، حيث يتم تخصيص الميكروكونترولر لمراقبة درجة حرارة الغرفة ، وتحويل المكيف أو سخان لوضع التشغيل ON ووضع الإيقاف OFF ، والتحكم في شاشة LCD ، والاستجابة لأي إعدادات جديدة لدرجة الحرارة من قبل المستخدم . من بين هذه المهام ، الثلاث مهام الأولى تكون غير حرجة للوقت ويتم تنفيذها بشكل مستمر في تسلسل واحدة تلو الآخرى ، داخل الحلقة الرئيسية . ولكن عندما يضغط المستخدم أي زر على لوحة الإعداد ، يجب أن يكون الميكروكونترولر قادرا على قراءته قبل أن يحرر المستخدم الزر. لذلك هذا الحدث يكون حساس (حرج) للوقت ، ويجب على الميكروكونترولر أن يتوقف عن كل ما يقوم به والاستجابة (الرد) على هذا الحدث ذات الأولوية المرتفعة . هذا ممكن من خلال استخدام المقاطعات interrupts . فى هذا الدرس سوف يتم أولا وصف نظام المقاطعة بشكل عام ثم توضيح كيفية التعامل معه في الميكروكونترولر PIC .
وكما ذكر أعلاه ، تشكل المقاطعات الأساس لفصل الأحداث ذات الحساسية للوقت عن الأحداث الأخرى وتنفيذها بطريقة ذات أولوية . المقاطعة تخبر الميكروكونترولر بترك كل ما يقوم به وتنفيذ برنامج آخر (روتين خدمة المقاطعة ISR ) المخزن في مكان محدد مسبقا في ذاكرة البرنامج . طلبات المقاطعة هي أحداث غير متزامنة مما يعني أنه يمكن حدوث طلب المقاطعة في أي وقت أثناء تنفيذ أحد البرامج . ولكن كلما حدث ذلك ، فإن وحدة المعالجة المركزية تنهى التعليمة الحالية وتخزن عنوان التعليمة التالية (عن طريق عداد البرنامج PC ) في ذاكرة المكدس stack بحيث يمكن للبرنامج الحالي من أن يستمر فى التنفيذ من حيث وقف بمجرد انتهاء روتين خدمة المقاطعة . عتدئذ اقفز وحدة المعالجة المركزية إلى موقع ذاكرة برنامج معين (المةقع 0x0004 فى الميكروكونترولر PIC )، حيث يبدأ روتين خدمة المقاطعة ISR . في نهاية روتين خدمة المقاطعة ، تنفيذ تعليمة العودة return تحميل العنوان الموجود في الجزء العلوي من المكدس مرة أخرى في عداد البرنامج ، ويتقدم التنفيذ من نفس النقطة حيث تم مقاطعة المعالج .
الميكروكونترولر لديه عدة مصادر للمقاطعات ، والتي يمكن أن تكون خارجية أو داخلية . مصادر المقاطعة الداخلية الأكثر شيوعا هي المؤقتات Timers وذاكرة EEPROM وموديول ADC والمقارن Comparator . المقاطعات الخارجية تنشأ في الأجهزة الطرفية وتصل إلى متحكم الميكروكونترولر من خلال واحد من أطرافه والمنافذ المرتبطة به.
المقاطعات يمكن أن يتم تمكينها أو تعطيلها بشكل عام globally ، وكذلك فإن كل مصدر مقاطعة يمكن تمكينه أو تعطيله بشكل فردى .
مصادر المقاطعة فى الميكروكونترولر PIC16F877A :



العائلة PIC16F87XA لديها ما يصل الى 15 من مصادر المقاطعة. ويسجل سجل التحكم في المقاطعة INTCON طلبات المقاطعات الفردية في بتات العلم flag bits . هذا السجل به أيضا بتات التمكين enable bits للمقاطعة الفردية والعمومية .
يسمح بت عموم المقاطعات GIE (INTCON<7>) بتمكين جميع المقاطعات (إذا تم تعيينها set) ، أو تعطيلها جميعا (إذا تم مسحه clear ) . عندما يتم تمكين بت عموم المقاطعات GIE ويتم تحديد بت علم المقاطعة فسوف يتم تفعيل المقاطعة على الفور . المقاطعات الفردية يمكن تعطيلها من خلال ما يقابلها من بتات التمكين في السجلات المختلفة. يتم تعيين بت المقاطعة الفردية بغض النظر عن حالة البت GIE . يتم مسح البت GIE عند إعادة تعيين Reset .
تعليمة "العودة من المقاطعة" RETFIE تخرج روتين المقاطعة ، فضلا عن تعيين set البت GIE ، وهو ما يعيد تمكين المقاطعات.
مقاطعة الطرف RB0/INT ، والمقاطعة عند تغيير المنفذ RB ، والمقاطعة نتيجة طفحان (تجاوز) المؤقت TMR0 موجودة بالسجل INTCON .
أعلام المقاطعة الطرفية موجودة فى سجلات الوظائف الخاصة PIR1 , PIR2 ، وبتات تمكين المقاطعة المناظرة موجودة فى سجلات الوظائف الخاصة PIE1 , PIE2 ، وبت تمكين المقاطعة الطرفية موجود فى السجل INTCON .
عندما يتم الاستجابة للمقاطعة ، يتم مسح البت GIE لتعطيل أي مقاطعة أخرى ، يتم دفع عنوان الرجوع الى المكدس ويتم تحميل عداد البرنامج بالعنوان 0004h . يمكن تحديد مصدر أو مصادر المقاطعة عن طريق تقصى بتات علم المقاطعة .
بت أو بتات علم المقاطعة يجب أن يتم مسحها في البرنامج قبل إعادة تمكين المقاطعات لتجنب تكرار المقاطعات .
بالنسبة لأحداث المقاطعة الخارجية ، مثل مقاطعة الطرف INT أو المقاطعة نتيجة تغيير المنفذ PORTB ، يكون زمن استجابة المقاطعة ثلاث أو أربع دورات تعليمة . يعتمد وقت الاستجابة الصحيح على زمن حدوث حدث المقاطعة . زمن الاستجابة هو نفسه لمدة دورة أو دورتى تعليمة .
يتم تحديد set بتات علم المقاطعة بصرف النظر عن حالة البتات PEIE , GIE المقابلة .

بعض مصادر المقاطعة :
المقاطعة الخارجية نتيجة تطبيق نبضة على الطرف RB0/INT :
المقاطعة الخارجية على الطرف RB0/INT هى مقاطعة تعمل بالحافة edge ، يتم اختيار نوع الحافة ، إما حافة صاعدة rising ( بتحديد set البت السادسة INTEDG بالسجل OPTION_REG<6> ) ، أو حافة هابطة ( بمسح clear البت INTEDG ) . عندما تظهر حافة صالحة على الطرف RB0/INT ، يتم تحديد set بت علم المقاطعة الخارجية INTF ، وهى البت الأولى بالسجل INTCON<1> . يمكن تعطيل هذه المقاطعة عن طريق مسح بت تمكينها INTE ، وهى البت الرابعة بالسجل INTCON<4> . بت العلم INTF يجب أن يتم مسحها فى البرنامج ، فى روتين خدمة المقاطعة ، قبل إعادة تمكين هذه المقاطعة . يمكن للمقاطعة الخارجية INT أن توقظ المعالج من النوم إذا كانت البت INTE قد تم تعيينها قبل الذهاب إلى النوم .

مقاطعة المؤقت TMR0 :
حدوث طفحان overflow(FFh → 00h) فى سجل المؤقت TMR0 سوف يحدد set بت العلم TMR0IF ، البت الثانية بالسجل INTCON<2> . يمكن تمكين / تعطيل هذه المقاطعة عن طريق تحديد set / مسح clear بت التمكين TMR0IE ، البت الخامسة بالسجل INTCON<5> .

المقاطعة نتيجة تغيير حالة أطراف المنفذ PORTB :
التغيير فى دخل الأطراف من 4 إلى 7 للمنفذ PORTB<7:4> ، تحدد set بت العلم RBIF وهى البت صفر للسجل INTCON<0> . يمكن تمكين / تعطيل هذه المقاطعة عن طريق تحديد / مسح بت التمكين RBIE ، وهى البت الرابعة للسجل INTCON<4> .



كل من هذه المقاطعات يمكن تمكينها أو تعطيلها بشكل فردي ، ويمكن أن تكون أكثر من مقاطعة واحدة نشطة في نفس الوقت . عند طلب مقاطعة ، ينتهي الميكروكونترولر من تنفيذ التعليمة الحالية، ويخزن قيمة عداد البرنامج في المكدس ، ويقفز إلى الغنوان 0004h في ذاكرة البرنامج ، حيث يقع روتين خدمة المقاطعة . ونظرا لأن جميع مصادر المقاطعة تجعل البرنامج يقفز إلى نفس المكان (0004h) ، فإنه يجب على المبرمج ، عند كتابة روتين خدمة المقاطعة ، أولا معرفة المصدر الذي طلب المقاطعة . ويتم ذلك من خلال قراءة البتات المناسبة في سجلات الوظيفة الخاصة ، INTCON و PIR1 ، المرتبطة بنظام المقاطعة . ويبين الشكل أدناه البتات في سجل التحكم في المقاطعة INTCON .

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 23, 2017 10:04 pm

تدريب 1 :
الغرض :
دراسة كيفية برمجة المقاطعة الخارجية نتيجة تطبيق نبضة على الطرف RB0/INT .

من أجل تهيئة المقاطعة INT ، يجب أن تتم العمليات التالية:
1- يجب أن يتم تهيئةالطرف RB0 كدخل (وهو الوضع الافتراضى ) .
2- يجب تعيين مصدر المقاطعة لتكون الإشارة إما بحافة هابطة أو حافة صاعدة ، باستخدام البت INTEDG بالسجل OPTION_REG .
3- يجب أن تكون بت علم المقاطعة الخارجية (البت INTF بالسجل INTCON ) ممسوحة (صفر) كحالة ابتدائية .
4- يجب تمكين بت عموم المقاطعات عن طريق تحديد (واحد) البت GIE بالسجل INTCON .
5- يجب تمكين بت المقاطعة الخارجية INT من خلال تحديد (واحد) البت INTE بالسجل INTCON .

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



يتم توصيل مفتاح ضاغط إلى الطرف RB0 ، هذا المفتاح سوف ينتج مقاطعة عند الضغط عليه . كما يتم توصيل أربع ليدات حمراء إلى الأطراف RC0-RC3 وليد أصفر إلى الطرف RD0 .
البرنامج الرئيسى هو عداد تصاعدى ثنائى 4-bit والذى يتزايد بمعدل واحد ثانية تقريبا . يتم إرسال قيمة الغداد إلى المنفذ PORTC والغرض على الأربع ليدات الحمراء . اليد الصفراء يتم تحويلها ON و OFF عند الضغط على المفتاح .
المفتاح فعال فى الحالة المنخفضة ولذلك يتم برمجة المقاطعة على الحافة الهابطة (تغيير من 5V إلى 0V ) ، من خلال جعل INTEDG = 0 (الحالة الابتدائية بواحد) .
يعتمد روتين خدمة المقاطعة ISR على التطبيق المحدد . ومع ذلك ، تطبق بعض الخطوات على جميع الحالات . على سبيل المثال ، يجب أن يبدأ روتين خدمة المقاطعة بالتحقق من الحدث المحدد الذي تسبب في المقاطعة (إذا تم تمكين أكثر من مقاطعة ) . في هذه الحالة ، يجب فحص البت INTF من السجل INTCON للتحقق من أن مصدر المقاطعة هو من الطرف RB0/INT .
وبالمثل ، يجب أن يتم مسح علم المقاطعة (البتINTF من السجل INTCON ) بواسطة روتين خدمة المقاطعة قبل العودة إلى البرنامج الرئيسي وإلا ستحدث سلسلة لا نهاية لها من المقاطعات . وذلك لأنه عند العودة فإن وحدة المعالجة المركزية سوف تجد علم المقاطعة لا يزال فى حالة تعيين set ويفترض أنها مقاطعة أخرى ويقفز مرة أخرى إلى روتين خدمة المقاطعة .
فى الميكروكونترولر ، يقوم المعالج تلقائيا بمسح بت عموم المقاطعات GIE بالسجل INTCON عندما تحجث مقاطعة . هذا يعنى أنه لا يمكن وقوع مقاطعة فى روتين خدمة المقاطعة ، وإلا تخيل الفوضى التى سوف تحدث ما لم يكن ينبغى هذا الحال .
عندما يقوم المعالج بتنفيذ عبارة الرجوع فى روتين خدمة المقاطعة ، يتم تحديد set البت GIE ويتم تمكين المقاطعات مرة أخرى .
فى هذا التدريب سوف نستخدم المترجم ميكروسى برو . فى هذا المترجم يتم كتابة روتين خدمة المقاطعة مثل أى برنامج فرعى (دالة) آخر لكن مع استخدام الاسم بالكلمة الخاصة (المحجوزة) interrupt . داخل روتين خدمة المقاطعة يتم اختبار بتات الأعلام المناسبة للتعرف على مصدر المقاطعة .
البرنامج :

الكود:

/*
Understanding Interrupts
*/
 
sbit LED at RD0_bit;  // Interrupt LED
unsigned short count;
 
// Interrupt service routine
void interrupt(){
 if(INTCON.INTF == 1) LED = ~LED;
 delay_ms(200);  // Key debounce time
 INTCON.INTF = 0;
}
 
void main() {
  TRISB.B0 = 1 ; // RB0 as input
  TRISC = 0;    // PORTC all outputs
  TRISD = 0 ; // PORTD all outputs
  PORTD = 0 ;

 INTCON = 0b10010000;  // Set GIEand INTE bits , INTCON.GIE=1; INTCON.INTE=1;
 OPTION_REG.INTEDG = 0; // External interrupt on falling edge of RB0/INT pin
 count = 0;
 LED = 0;
 PORTC = count;
 do {
  count ++;
  if (count ==16) count =0;
  PORTC = count;
  delay_ms(1000);
 }while (1); // infinite loop 
}

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

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 23, 2017 10:10 pm

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




البرنامج :

الكود:

/*
 Etxernal Interrupt (INT- RB0)
 * Description:
    This is a simple interrupt demostration project.
    All LEDs on PORTD will flash utill interrupt occurs (RB0 is pressed).
    Interrupt will set local flag , which will cause Flashing routine to be executed.
  */

bit flag;

void Delay250() {
  Delay_ms(250);
}

void Delay150() {
  Delay_ms(150);
}

void Flash () {            // Flashing rutine
  PORTD.F1 = 1;
  Delay150();
  PORTD.F1 = 0;
  Delay250(); Delay250();
  PORTD.F1 = 1;
  Delay150();
  PORTD.F1 = 0;
  Delay250(); Delay250();
}

void interrupt(){          // Interrupt rutine
  if(INTF_bit == 1 ) {    // Checks Receive Interrupt Flag bit
    flag      = 1;          // Set local interrupt flag
    INTF_bit = 0;          // Clear Interrupt Flag
  }
}

void main() {
  flag  = 0;              // Varialbe initialisation
  TRISB  = 1;              // Set PORT B (only RB0) as input
  TRISD  = 0;              // Set PORT D as output
  PORTD  = 0x00;            // Set all pin on PORT D Low
  INTEDG_bit = 1;          // Set interrupt on rising edge
  INTF_bit  = 0;          // Clear INT0 flag
  INTE_bit  = 1;          // Enable INT0 interrupts
  GIE_bit    = 1;          // Enable GLOBAL interrupts

  while(1) {
    PORTD = 0xFF;            // Set all pin on PORT D High
    Delay250();            // Wait for some time
    PORTD = 0x00;            // Set all pin on PORT D Low
    Delay150();            // Wait for some time
    if(flag) {              // Checks local interrupt flag
      Flash();            // Do something
      flag = 0;            // Reset local interrupt flag
    }
  }
}




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



البرنامج :

الكود:

/*
 * Project name:
    Etxernal Interrupt (RB4:RB7)
  * Description:
    This is a simple interrupt demostration project.
    All LEDs on PORTD will flash utill interrupt occurs.
    Interrupt will set local flag, which will cause Flashing routine to be executed.
    Depending on pressed button (RB4:RB7) different Flashing routine will be executed.
*/


char pressedButton;
bit flag;

void interrupt(){              // Interrupt rutine
  if(RBIF_bit == 1 ) {        // Checks for Receive Interrupt Flag bit
    flag  = 1;                // Set local interrupt flag
    RBIF_bit = 0;              // Clear Interrupt Flag
    if (PORTB.F7 == 1){        // Checks if the RB7 is pressed
      pressedButton = 7;
    }
    if (PORTB.F6 == 1){        // Checks if the RB6 is pressed
      pressedButton = 6;
    }
    if (PORTB.F5 == 1){        // Checks if the RB5 is pressed
      pressedButton = 5;
    }
    if (PORTB.F4 == 1){        // Checks if the RB4 is pressed
      pressedButton = 4;
    }
  }
}

void Delay250() {
  Delay_ms(250);                // Waits for 250 ms
}

void Delay150() {
  Delay_ms(150);                // Waits for 150 ms
}

void FlashIt(char hexCode){    // Flashes LEDs two times
  PORTD = hexCode;              // Writes hex to to PORTD
  Delay150();                  // Short pause
  PORTD = 0;                    // Clears PORTD
  Delay250(); Delay250();      // Pause
  PORTD = hexCode;              // Writes hex to to PORTD second time
  Delay150();                  // Short pause
  PORTD = 0;                    // Clears PORTD
  Delay250(); Delay250();      // Pause
}


void main() {                 
  flag          = 0;          // Varialbe initialisation
  pressedButton = 0;
 
  TRISB  = 0xFF;              // Set PORT B as input
  TRISD  = 0;                  // Set PORT D as output
  PORTD  = 0x00;              // Set all pin on PORT D Low
 
  RBIE_bit  = 1;              // Enable Port B Interrupt-On-Change
  RBIF_bit  = 0;              // Clear IOC flag
  GIE_bit  = 1;              // Enable GLOBAL interrupts


  while(1) {
    PORTD = 0xFF;              // Set all pin on PORT D High
    Delay250();                // Wait for some time
    PORTD = 0x00;              // Set all pin on PORT D Low
    Delay150();                // Wait for some time

    if(flag) {
      switch(pressedButton) {  // Depending on value(button pressed), calls FleshIt function with different argument
      case 4:
          FlashIt(0x03);
          pressedButton = 0;
      break;
      case 5:
          FlashIt(0x0C);
          pressedButton = 0;
      break;
      case 6:
          FlashIt(0x30);
          pressedButton = 0;
      break;
      case 7:
          FlashIt(0xC0);
          pressedButton = 0;
      break;
      default:
          FlashIt(0xAA);      // Just in case
      break;
      }
      flag = 0;                // Reset flag variable
    }
  }
}
 

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 23, 2017 10:13 pm

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




البرنامج :

الكود:

/*
 * Project name:
    Peripheral Interrupt (Interrupt while reciving data over UART)
 
 * Description:
    This is a simple interrupt demostration project.
    uC will send some data for connectivty test.
    Received data will be saved in buffer using interrut.
    Last recived character will be diplayed on portD.
*/

char rxbuff[20];                    // Buffer variable for storing data sent from master
char rxidx;                        // Counter for data writen in buffer

void interrupt() {                  // Interrupt rutine
  if(RCIF_bit == 1) {            // Checks for Receive Interrupt Flag bit
    rxbuff[rxidx] = UART1_Read();  // Storing read data
    rxidx++;                      // Incresing counter of read data
    if(rxidx >= 20)                // Checks if data is larger than buffer
      rxidx = 0;                  // Reset counter
  }
}

void main() {
  rxidx  = 0;                      // Initialisation of variable
 
  TRISD  = 0;                      // Configure PORTD as output

  UART1_Init(19200);                // Initialize UART module at 19200 bps
  Delay_ms(100);                    // Wait for UART module to stabilize

  UART1_Write_Text("Start");        // Send text
  UART1_Write(13);                  // ASCII carriage return
  UART1_Write(10);                  // ASCII line feed (new line)

  PORTD = 0xFF;                      // Set all pin on PORT D High
  Delay_ms(100);                    // Wait for some time
  PORTD = 0x00;                      // Set all pin on PORT D Low

  RCIE_bit = 1;                    // turn ON interrupt on UART1 receive
  RCIF_bit = 0;                    // Clear interrupt flag
  PEIE_bit  = 1;                    // Enable peripheral interrupts
  GIE_bit  = 1;                    // Enable GLOBAL interrupts

  while(1) {
    if (rxidx == 0) {              // Nothing is read, or buffer overflows
      PORTD = rxbuff[rxidx];        // Do something(Show first char that will be overwriten)
    }
    else {
      PORTD = rxbuff[rxidx-1];      // Show binary value of the read character on PORT D
    }
  }
}

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الأحد يوليو 23, 2017 10:24 pm

تدريب 5 : التعامل مع مقاطعات متعددة
المقاطعات هى أحداث مجدولة والتى تجعل الميكروكونترولر PIC "يعلق" برنامجه القائم على تنفيذه ويقوم بتشغيل جزء من برنامج (برنامج فرعى يسمى روتين المقاطعة interrupt routine) مقترن بحدث .
عند اكتمال روتين المقاطعة يستمر PIC فى تنفيذ سريان البرنامج من عند نفس النقطة التى كان قد علق عندها التنفيذ.
مصادر المقاطعة تختلف تبعا لنوع الميكروكونترولر . على سبيل المثال الميكروكونترولر PIC 16F877A له 15 مصدر للمقاطعة مثل :
• المقاطعة بالمؤقت Timer0 عند حدوث طفحان بالمؤقت .
• المقاطعة عن تغيير حافة النبضة الخارجية على الطرف RB0 (تعرف بالمقاطعة الخارجية) .
• المقاطعة عند وصول البيانات التسلسلية خلال الوحدة USART .
• المقاطعة بالمحول من تناظرى لرقمى ADC عند انتهاء التحويل .
وغيرها من المقاطعات .
مترجم الميكروسى برو يتضمن دالة سابقة التعريف من أجل تنفيذ المقاطعة ، هذه الدالة هى "دالة أو روتين المقاطعة" وهى بالصيغة التالية :
void interrupt (void);
يجب إعلان هذه الدالة قبل الدالة الرئيسية .
عند حدوث مقاطعة يتم استدعاء "دالة المقاطعة" تلقائيا عن طريق البرنامج ، داخل هذه الدالة يجب تحديد ما هى المقاطعات التى يتم بدؤها وأعلام (معلمات - علامات) flags كل مقاطعة .
لإعداد المقاطعات يجب تفعيل البتات المناظرة بسجلات المقاطعة . فى الميكروكونترولر PIC16F877A ، على سبيل المثال ، سجلات المقاطعة هى : INTCON, PIR1, PIR2, PIE1 , PIE2 . الشكل التالى يبين هذه السجلات يالميكروكونترولر PIC 16F877A :



لتنفيذ المقاطعات يجب اتباع الخطوات المناسبة للإعداد مع مرعاة ما يلى :
• أولا يتم تفعيل المقاطعات المطلوب استخدامها عن طريق بت التمكين IEالمناسب مثل :
TMR0IE, INTE, RCIE وغيرها .
• يجب عدم تمكين أعلام المقاطعات مثل :
TMR0IF, INTF, RCIF وغيرها .
• يجب تمكين مقاطعات الطرفيات عندما يتطلب ذلك ، على سبيل المثال المقاطعات التابعة للسجلات :
PIE1 و PIE2.
• وأخيرا يتم تحديد set بت تمكين عموم المقاطعات : GIE .


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

الكود:

//1-declaration interrupt function.
void interrupt ( void )
{
   //A-Declaration of variables used in interrupt function.
   char Data;
   //B-Evaluates whether the interrupt is triggered by Timer 0, TMR0IF
   if( INTCON.F2==1 )
   {
      //It complements the bit value RB1.
      if(PORTB.F1==1)
      PORTB.F1=0;
      else
      PORTB.F1=1;
      // Turned off Timer 0 Flag.
      INTCON.F2=0;
   }
   //C-Evaluates whether the external interrupt is triggered.
   // INTF
   if( INTCON.F1==1 )
   {
      //It complements the bit value RB2.
      if(PORTB.F2==1)
      PORTB.F2=0;
      else
      PORTB.F2=1;
      //It turns off the external interrupt flag.
      INTCON.F1=0;
   }
   //D-Evaluates whether the interruption triggered by serial reception.
   if( PIR1.F5 ==1)
   {
      //It reads the input data.
      Data = UART1_Read();
      //Confirmation information is sent.
      UART1_Write_Text("Input data: ");
      //It sends the data received.
      UART1_Write(Data);
      UART1_Write(13); //ASCII code is sent enter.
      UART1_Write(10); //and sends carriage return code.
      //It reception apparatus for serial flag.
      PIR1.F5 = 0;
   }
}

void main( void )
{
   //Ports are configured.
   TRISB = 0b00000001;
   PORTB = 0;
   //Activates the serial receive interrupt.
   PIE1 = 0b00100000;
   //Other interrupt sources are disabled .
   PIE2 = 0;
   //Turn off interrupt flags.
   PIR2 = 0;
   PIR1 = 0;
   //Setting the Timer 0 to 65.535 m Sec
   OPTION_REG=0b11000111;
   //Configuring the serial port at 9600 bps.
   UART1_Init(9600);
   //Global interrupts are enabled,
   //for Timer 0, and external.
   INTCON = 0b11110000;
   while(1) //Infinite Loop.
   {
   }
}

لمحاكاة هذا البرنامج ببرنامج إيزيس يتم جلب الأجهزة التالية :
16F877A, RES, BUTTON, LED-RED والوحدة الطرفية التخيلية والأوسليسكوب .
بعد تشغيل المحاكاة يجب التفاعل مع الوحدة الطرفية لإرسال بيانات , بالمفتاح الضاغط يجب أن تشاهد حالة الليد وخرج الأوسليسكوب وعرض شكل الموجة المربعة يتغير كل 65.535 msec , تبعا للمؤقت Timer 0 .
الدائرة الكهربية :




Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الثلاثاء يوليو 25, 2017 7:38 pm

المؤقتات 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 .

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الثلاثاء يوليو 25, 2017 10:00 pm

التدريب على نظام المؤقت :
مقدمة :
فى البداية سوف نتناول خطوة بخطوة إعداد الأجزاء المختلفة لموديول المؤقت باستخدام سجل الخيارات 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 . يتم استخدام معامل القسمة والمقاطعة بنفس إسلوب نظام المؤقت .

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الثلاثاء يوليو 25, 2017 10:11 pm

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



توليد تأخير زمنى بحوالى واحد ثانية باستخدام موديول Timer0 كمؤقت . تردد الكريستال 4 MHz لذلك يكون زمن دورة التعليمة هو واحد ميكروثانية 1µs . لتوليد فترة تأخير بقيمة واحد ثانية يجب أن يعد المؤقت مليون دورة 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
}
 

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الثلاثاء يوليو 25, 2017 10:27 pm

التدريب على نظام عمل موديول المؤقت 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
}


النتائج :




Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin في الثلاثاء يوليو 25, 2017 10:32 pm

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



يقوم البرنامج بعمل مهمتين فى نفس الوقت ، المهمة الظاهرة والعادية هى إصدار صوت من سماعة بصفة مستمرة ، ومهمة فى الخلفية وهى وميض ليد عن طريق توليد نبضة كل واحد ثانية باستخدام موديول المؤقت 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
 

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin أمس في 1:31 pm

أفضل طريقة لانتخاب وحدات العرض 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;

}
}
 

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

رد: ما هو الميكروكونترولر Microcontroller ؟

مُساهمة من طرف Admin أمس في 5:36 pm

البرنامج الثانى باستخدام 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;

}
}

Admin
Admin

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

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

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

صفحة 4 من اصل 4 الصفحة السابقة  1, 2, 3, 4

استعرض الموضوع السابق استعرض الموضوع التالي الرجوع الى أعلى الصفحة

- مواضيع مماثلة

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