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

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

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

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

مُساهمة من طرف Admin في الثلاثاء يونيو 13, 2017 1:26 pm

السفن سجمنت نوع الكاثود المشترك ومفسر الشفرة 7448 والميكروكونترولر PIC16F628 وعداد تصاعدى تنازلى من 00 إلى 99 :
الغرض :
إنشاء عداد تصاعدى / تنازلى من 00 إلى 99 يمكن أن يستخدم فى الكثير من التطبيقات مثل عد السيارت فى موقف السيارات أو عدد الأشخاص فى مكان ما .
قد يشكل حساب كود السفن سيجمنت فى كل مرة شىىء من الإزعاج للبعض .
هل هناك طريقة لاستخدام القيمة العشرية فقط لتعرضها السفن سيجمنت ؟
نعم ، الدائرة المتكاملة المسماة مفسر الشفرة من BCD إلى سفن سيجمنت ( 7447 للأنود المشترك و 7448 للكاثود المشترك ) تقوم بذلك نيابة عنك .

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







سوف نستخدم الدائرة المتكاملة 7448 كمفسر للشفرة من BCD إلى سفن سيمنت ، ومن ثم يجب أن نستخدم وحدتين سفن سيجمنت نوع "الكاثود المشترك" ، ويتم توصيل الخطوط A,B,C,D,E,F,G على التوازى مع استخدام طريقة الانتخاب بين كاثودى الوحدتين .
البرنامج عبارة عن عداد تصاعدى / تنازلى من 00 إلى 99 باستخدام 2 مفتاح ضاغط ( تمثل أى نوع من حساسات الدخل الرقمى المناسبة ) أحدهما للتزايد والآخر للتناقص .
شرح خطوات البرنامج :
1- فى البداية يتم استخدام الموجه #define فى تعريف وإنشاء مسميات سهلة ومتعارف عليها بدلا من مسميات خاصة . على سبيل المثال تسمية طرف توصيل مفتاح التزايد PORTA.F0 باسم Up وطرف توصيل مفتاح التناقص PORTA.F1 باسم Down وهكذا ، كما يلى :

الكود:
#define Up  PORTA.F0      //  We can write Up instead of PORTA.F0  ...
#define Down  PORTA.F1
 #define disp_unit1  PORTA.F2    //  We can write disp_uinit1 instead of PORTA.F2  ...
#define disp_unit2  PORTA.F3

2- إعلان (تعريف) المتغيرات وتخصيص قيم لها عند الرغبة . هنا يتم إعلان متغير العدد الكلى المراد عرضه Number ( يقع بين 00 و 99 ) ومتغير قيمة خانة آحاده Ones ومتغير قيمة خانة عشراته Tens ( تقع بين 0 و 9) من نوع char والتى تعنى ضمنيا (unsigned) char ( بين 0 و 255 ) ، مع تخصيص صفر للعدد Number=0 كحالة ابتدائية كما يلى :

الكود:
char Number=0 , Ones , Tens ;    // Variables

3- من المفضل تقسيم البرنامج إلى دوال منفصلة قدر المستطاع ، لتسهيل فهم وتتبع البرنامج . هنا سوف نقوم بإنشاء الدوال التالية :
أ‌- دالة العرض Display() : وهى دالة فارغة void لا تعود بقيمة وليس لها بارامترات مرتبطة بها بل يتم تنفيذ العبارات التى تحتوى عليها فقط ، وتكون بالصيغة التالية :

الكود:
void Display() //  Display function
{
…..
}

هذه الدالة بدورها تنقسم إلى قسمين هما :
• قسم استخراج خانة العشرات Tens وخانة الآحاد Ones من العدد الكلى Number ، وذلك عن طريق استخدام عامل القسمة "/" وعامل باقى القسمة "%" . نتيجة "قسمة عدد صحيح على عدد صحيح أخر" (كما هو الحال هنا) تكون العدد الصحيح ويتم تجاهل الكسر أو باقى القسمة (على سبيل المثال نتيجة قسمة 5 على 3 تكون 5/3 = 1 ) فى حين أن نتيجة " خارج قسمة عدد على عدد صحيح آخر " تكون عدد صحيح هو باقى القسمة ( مثال :نتيجة باقى قسمة 5 على 3 هو 5%3 = 2 ) . وبناء على ذلك نتيجة "قسمة العدد الصحيح Number (المكون من آحاد وعشرات) على العدد الصحيح "10 تكون العدد الصحيح المناظر لخانة العشرات لهذا العدد أى Tens=Number/10 . فى حين أن نتيجة "باقى قسمة العدد الصحيح Number (المكون من آحاد وعشرات) على العدد الصحيح "10 تكون العدد الصحيح المناظر لخانة الآحاد لهذا العدد أى Ones=Number%10 .

الكود:
Tens=Number/10; // Extracr : Tens & Ones from Number
Ones=Number%10;

• قسم الانتخاب وإرسال (تحميل) البيانات والخاص بوحدات السفن سيجمنت . حيث يتم تفعيل أحد وحدتى السفن سيجمت ، (وحدة العشرات disp_unit1=0 ، على سبيل المثال " كاثود مشترك" ) وفصل الوحدة الأخرى ( تكون وحدة الآحاد disp_unit2=1 ) مع تحميل بيانات الوحدة الفعالة (العشرات PORTB=Tens ) , ثم يتم العكس . كما يتم إجراء تأخير بسيط للسماح بعدم ظهور تداخل أو ظلال (أشباح) أثناء العرض كما يلى :

الكود:
disp_unit2=1;  // Ones unit disp_unit2 => off
 PORTB=Tens; // Load Tens Data
 disp_unit1=0; // Tens unit disp_unit1 => on
 delay_ms(3); // Delay

 disp_unit1=1; // Tens unit disp_unit1 => off
 PORTB=Ones; // Load Ones Data
 disp_unit2=0; // Ones unit disp_unit2 => on
delay_ms(3); // Delay

وتكون دالة العرض كما يلى :

الكود:
void Display() //  Display function
{
 Tens=Number/10; // Extracr : Tens & Ones from Number
 Ones=Number%10;
 
 disp_unit2=1;  //off => ones
 PORTB=Tens;
 disp_unit1=0; //on => tens
 delay_ms(3);
 
 disp_unit1=1; //off => tens
 PORTB=Ones;
 disp_unit2=0; //on => ons
 delay_ms(3);
}


ب‌- دالة تهيئة وإعداد أجهزة الميكروكونترولر المستهدف Setup() وهو هنا PIC16F628 كما يلى :

الكود:
void Setup()
{
 CMCON=7;    //All pins digital I/O
 TRISA.f0=1; TRISA.f1=1;  TRISA.f2=0;  TRISA.f3=0;//PORTA setup
 TRISB=0; //PORTB=0;                              //PORTB setup
 disp_unit1=1; disp_unit2=1;                            //Initial => off
}

4- فى النهاية يتبقى الدالة الرئيسية للبرنامج main() ، وفيها نبدأ باستدعاء دالة التهيئة Setup() ثم الدخول فى حلقة غير منتهية while(1) ، وفيها ننتظر تحقق شرط الضغط على أى من مفتاح التزايد if(Up) أو مفتاح التناقص if(Down) لتنفيذ تزايد Number++ أو تناقص Number— العدد Number بواحد . فى كل حالة يتم وضع بعض الشروط للتنفيذ السليم للبرنامج . على سبيل المثال لتجنب تغيير العدد أثناء الضغط يتم وضع شرط استمرار العرض حتى إزالة الضغط بحلقة while(Up) و حلقة while(Down) . كما أنه فى حالة التزايد ووصول العدد الكلى Number إلى القيمة 100 يتم استبدالها بالقيمة 0 بالعبارة if(Number==100)Number=0 , وفى حالة التناقص وصول العدد الكلى Number إلى القيمة 0 يتم استبدالها بالقيمة 100 بالعبارة if(Number==0)Number=100 .


البرنامج :

الكود:
#define disp_unit1  PORTA.F2 //  We can write disp_uinit1 instead of PORTA.F2  ...
#define disp_unit2  PORTA.F3
#define Up  PORTA.F0
#define Down  PORTA.F1

char Number=0,Ones,Tens; // Variables

void Display() //  Display function
{
 Tens=Number/10; // Extracr : Tens & Ones from Number
 Ones=Number%10;
 
 disp_unit2=1;  //off => ones
 PORTB=Tens;
 disp_unit1=0; //on => tens
 delay_ms(3);
 
 disp_unit1=1; //off => tens
 PORTB=Ones;
 disp_unit2=0; //on => ons
 delay_ms(3);
}
//*****************************************************************
void Setup()
{
 CMCON=7;    //All pins digital I/O
 TRISA.f0=1; TRISA.f1=1;  TRISA.f2=0;  TRISA.f3=0;//PORTA setup
 TRISB=0; //PORTB=0;                              //PORTB setup
 disp_unit1=1; disp_unit2=1;                            //Initial => off
}

//*****************************************************************

void main()
{
 Setup();
 while(1)
        {
          if(Up) // Press Up => PORTA.f0 high
                {
                    Number++;
                    if(Number==100)Number=0;
                    while(Up) // To avoid an increase in number wait until release => PORTA.f0 low.
                                  {
                                  Display();
                                  }
                    }

        if(Down) //Press Up => PORTA.f1 high
                    {
                    if(Number==0)Number=100;
                    Number--;
                    while(Down) // To avoid an increase in number wait until release => PORTA.f1 low.
                                  {
                                  Display();
                                  }
                    }

        Display();
        }
}
 

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الثلاثاء يونيو 13, 2017 2:56 pm

عداد تصاعدى / تنازلى من 0000 إلى 9999 بأربع وحدات سفن سيحمنت ومفسر شفرة 7448 :
البرنامج :

الكود:
#define disp_unit1  PORTA.F2              //  Thousands Digit
#define disp_unit2  PORTA.F3              //Hundreds  Digit
#define disp_unit3  PORTA.F6              //Tens Digit
#define disp_unit4  PORTA.F7              //Ones Digit
#define Up  PORTA.F0
#define Down  PORTA.F1


unsigned Number=0,Ones,Tens,Hundreds,Thousands ,rem ; // Variables
void Display() //  Display function
{
Thousands = Number/1000;  // Thousands
rem = Number%1000 ;        // reminder
Hundreds  = rem/100;      // Hundreds
rem = rem%100 ;            // reminder
Tens = rem/10;            // Tens
Ones = rem%10;            //Ones
disp_unit2=1;              // off
disp_unit3=1;              // off
disp_unit4=1;              // off
PORTB=Thousands ;          //Load  Thousands Data
disp_unit1=0;              // Thousands => on
delay_ms(3);
 disp_unit1=1;              // off
disp_unit3=1;              // off
disp_unit4=1;              // off
PORTB=Hundreds ;                //Load  Hundreds Data
disp_unit2=0;                // Hundreds => on
delay_ms(3);
disp_unit1=1;              // off
disp_unit2=1;              // off
disp_unit4=1;              // off
PORTB=Tens ;                //Load  Tens Data
disp_unit3=0;                // Tens => on
delay_ms(3);

disp_unit1=1;              // off
disp_unit2=1;              // off
disp_unit3=1;              // off
PORTB=Ones ;                //Load Ones Data
disp_unit4=0;                // Ones => on
delay_ms(3);
}
//*****************************************************************
void Setup()
{
 CMCON=7;    //All pind digital I/O
 TRISA.f0=1; TRISA.f1=1;  TRISA.f2=0;  TRISA.f3=0;TRISA.f6=0;TRISA.f7=0;        //PORTA setup
 TRISB=0; PORTB=0;                              //PORTB setup
 disp_unit1=1; disp_unit2=1;disp_unit3=1;disp_unit4=1;//Initial => off
}
//*****************************************************************
void main()
{
 Setup();
 while(1)
        {
          if(Up)                // Press Up => PORTA.f0 high
                    {
                    Number++;
                    if(Number==10000)Number=0;
                    while(Up)        // To avoid an increase in number wait until release => PORTA.f0 low.
                                  {
                                  Display();
                                  }
                    }

        if(Down) //Press Up => PORTA.f1 high
                    {
                    if(Number==0)Number=10000;
                    Number--;
                    while(Down) // To avoid an increase in number wait until release => PORTA.f1 low.
                                  {
                                  Display();
                                  }
                    }

        Display();
        }
}
 

النتيجة :


Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الثلاثاء يونيو 20, 2017 12:17 am

وحدة عرض الحروف LCD :
وحدة عرض الحروف LCD مكونة من وحدات (موديولات) جاهزة . ميزة هذه الوحدات أنها تحتوى على ناقل للبيانات data bus وناقل للتحكم control bus . للتعامل مع هذه الأجهزة يوجد بمترجم الميكروسى برو مكتبات معرفة مسبقا (جاهزة) للتحكم فى وحدات LCD . الشكل التالى يبين المظهر الطبيعى ومنظر هذه الوحدات فى برنامج إيزيس ISIS :



تقوم وحدات العرض LCD بعرض الحروف التى تغذى بها فى شكل كود أسكى ASCII code . بالإضافة إلى كود أسكى ، يمكنها أن تعرض الحروف المصصمة بمعرفة المبرمج ، ميزة أخرى لوحدة العرض LCD ، وهى أن ناقل توصيل البيانات الطبيعى عبارة عن 8 خطوط ، لكن يمكن إعدادها لكى تعمل فقط بأربعة خطوط للبيانات . هذه الميزة توفر من عدد الأطراف المستخدمة ولكن على حساب تقليل سرعة نقل البيانات . المكتبة الجاهزة بالميكروسى معدة لتعمل بأربعة بتات 4-bit .
لعرض المكتبة الجاهزة لهذا الجهاز وللأجهزة الأخرى والمتواجدة بالميكروسى ، يجب عليك النقر على لوحة الأدوات الموجودة على الجانب الأيمن لنافذة تحرير البرنامج ، يتم التعرف على هذه اللوحة بعلامة التبويب التى تحتوى على العنوان Library Manager . عندما تنقر هذا التبويب تظهر لك نافذة بها قائمة بالمكتبات المختلفة والتى من الممكن العمل بها مع الميكروكونترولر المستخدم . فى هذه النافذة سوف تجد مكتبة باسم Lcd ، حيث يمكنك النقر على إى دالة واردة بالمكتبة لرؤية تعليمات الاستخدام المناظرة . الشكل التالى يوضح مظهر هذه النافذة :




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

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


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

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

الكود:
void main (void)
{
   Lcd_init (); // Start the LCD.
   while (1) // infinite loop.
   {
   }
}
 

ويصبح كود البرنامج كما يلى :

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


void main (void)
{
   Lcd_init (); // Start the LCD.
   while (1) // infinite loop.
   {
   }
}

بعد تنفيذ الكود السابق تكون وحدة العرض LCD جاهزة لعرض الحروف ، بدءا من الموقع الموجود بالسطر(الصف) الأول والعامود الأول والذى يدل علية مؤشر يومض .
تصنع وحدات عرض الحروف فى أشكال وألوان متعددة حيث تتوفر بشاشة خضراء أو زرقاء أو صفراء . ويتم عرض الحروف فى شكل مصفوفة حروف مثل 2 صف مع 16 عامود وتعرف باسم 2x16 وبنفس الطريقة يوجد
1x16, 2x16, 2x8, 2x20, 4x20 وغيرها . على سبيل المثال ، سوف نستخدم وحدة عرض 2X16 .
لبدء محاكاة LCD ببرنامج إيزيس يتم جلب الأجهزة LM016L و PIC16F628A . الاسم المرجعى LM016L فى إيزيس هو لوحدة عرض 2X16 . وأخيرا يكون التوصيل كما فى الدائرة التالية:




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





Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الثلاثاء يونيو 20, 2017 3:12 pm

الخطوة التالية هى كتابة (طباعة) معلومات على الشاشة ، ولهذا الغرض يمكنك استخدام أربع دوال . دالتان منهم تسمحان لك بكتابة الأحرف characters ، والدالتان الأخريان تسمحان لك بكتابة السلاسل النصية strings .
يمكنك كتابة الحروف بطريقتين ، الأولى ، ببساطة كتابة الحروف بترتيب متسلسل معروف لوحدة العرض والطريقة الثانية كتابة الحروف فى السطر والعامود الذى يحدده المبرمج .

دوال كتابة (طباعة) الأحرف Functions to print characters
الدالة الأولى لكتابة الأحرف هى الدالة :

الكود:
  Lcd_Chr_Cp (char out_char);


هذه الدالة يتم استدعاؤها عند كتابة حرف من حروف كود أسكى ASCII code ، الموجود فى بارامتر الدخل out_char . وعند إحساس وحدة العرض بالأمر بكتابة حرف جديد فإن المؤشر ينتقل تلقائيا للموقع التالى مباشرة . لفهم أداء هذه الدالة راقب وحلل المثال التالى :

الكود:
 void main (void)
{
        Lcd_init ();                   // Start the LCD.
        Lcd_Chr_Cp('H');        // These functions printed letter by letter the word "Hello".
        Lcd_Chr_Cp('e');
        Lcd_Chr_Cp('l');
        Lcd_Chr_Cp('l');
        Lcd_Chr_Cp('o');
        while (1)                     // infinite loop.
        {
        }
}

ويصبح البرنامج بالصيغة التالية :

الكود:
// Lcd_Chr_Cp (char out_char);
// Prints character on Lcd at current cursor position.
//Both variables and literals can be passed as a character.

// Define 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 connection definition

void main (void)
{
        Lcd_init ();                   // Start the LCD.
        Lcd_Chr_Cp('H');        // These functions printed letter by letter the word "Hello".
        Lcd_Chr_Cp('e');
        Lcd_Chr_Cp('l');
        Lcd_Chr_Cp('l');
        Lcd_Chr_Cp('o');
        while (1)                     // infinite loop.
        {
        }
}
 

الشكل التالى يبين المحاكاة :



لكتابة حروف من خلال إحداثيات الصفوف والأعمدة نستخدم الدالة :

الكود:
 Lcd_Chr (char row, char column, char out_char);

هذه الدالة تطبع الحرف out_char بالصف row والعامود column . المثال التالى يوضح لك هذا المفهوم :

الكود:
void main (void)
{
   Lcd_init ();                   // Start the LCD.
   Lcd_Chr_Cp ('H');        // These functions printed letter by letter the word "Hello".
   Lcd_Chr_Cp ('e');
   Lcd_Chr_Cp ('l');
   Lcd_Chr_Cp ('l');
   Lcd_Chr_Cp ('o');
   Lcd_Chr (1, 6, '1');           // prints the character 1, at row 1, column 6
   Lcd_Chr (2, 7, '2');           // prints the character 2, at row 2, column 7
   Lcd_Chr (3, 8, '3');           // prints the character 3, at row 3, column 8
   Lcd_Chr (4, 9, '4');           // Prints the character 4, at row 4, column 9
   while (1)                        // infinite loop.
   {
   }
}

 

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

الكود:

// Lcd_Chr (char row, char column, char out_char);
// Prints character on Lcd at specified position.
//Both variables and literals can be passed as a character.

// Define 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 connection definition

 void main (void)
{
   Lcd_init ();                   // Start the LCD.
   Lcd_Chr_Cp ('H');        // These functions printed letter by letter the word "Hello".
   Lcd_Chr_Cp ('e');
   Lcd_Chr_Cp ('l');
   Lcd_Chr_Cp ('l');
   Lcd_Chr_Cp ('o');
   Lcd_Chr (1, 6, '1');           // prints the character 1, at row 1, column 6
   Lcd_Chr (2, 7, '2');           // prints the character 2, at row 2, column 7
   Lcd_Chr (3, 8, '3');           // prints the character 3, at row 3, column 8
   Lcd_Chr (4, 9, '4');           // Prints the character 4,at row 4, column 9
   while (1)                        // infinite loop.
   {
   }
}
 


الشكل التالى يبين المحاكاة :



دوال كتابة (طباعة) سلاسل النصوص Functions to print text strings :
أيضا كتابة السلاسل النصية إما أن يتم كتابتها فى موقع المؤشر الحالى (CP) وفق سريان الكتابة أو تكتب فى موقع يحدد بإحداثيات الصف والعامود .
لكتابة سلسلة نصية عند الموقع الحالى لمؤشر الكتابة نستخدم الدالة التالية :

الكود:
Lcd_Out_Cp (char * text); 

هذه الدالة لها بارامتر دخل واحد وهو مؤشر للسلسلة النصية والتى تسمى هنا text . للتعرف على استخدام هذه الدالة راقب وحلل هذا المثال :

الكود:
 
void main (void)
{
   Lcd_init ();             // Start the LCD.
   Lcd_Out_Cp ("Hello World ...");
   while (1)             // infinite loop.
   {
   }
}

يمكن تنفيذ هذه الدالة مع سلسلة من الثوابت أو من المتغيرات ، نعرف السلاسل بالأقواس المزدوجة فى بدايتها وفى نهايتها , على سبيل المثال "Hello World ...", ، صيغة المتغير يتم إعلانها بالشكل :

الكود:
char Text [20] = "Hello World ..." 

البرنامج :

الكود:

// Lcd_Out_Cp (char * text);
// Prints text on Lcd at current cursor position.
//Both string variables and literals can be passed as a text.

// Define 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 connection definition

void main (void)
{
   Lcd_init ();             // Start the LCD.
   Lcd_Out_Cp ("Hello World ...");
   while (1)             // infinite loop.
   {
   }
}


الشكل التالى يبين المحاكاة :




لكتابة السلسلة النصية إبتداء من نقطة إحداثيات محددة نستخدم الدالة :

الكود:
Lcd_Out (char row, char column, char * text);

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

الكود:
void main (void)
{
   Lcd_init ();                // Start the LCD.
   Lcd_Out (1, 1, "Row 1, Column 1");
   Lcd_Out (2, 2, "Row 2, Column 2");
   while (1)                // infinite loop.
   {
   }
}
 


البرنامج :

الكود:

// Lcd_Out (char row, char column, char * text);
// Prints text on Lcd starting from specified position.
//Both string variables and literals can be passed as a text.

// Define 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 connection definition

void main (void)
{
   Lcd_init ();                // Start the LCD.
   Lcd_Out (1, 1, "Row 1, Column 1");
   Lcd_Out (2, 2, "Row 2, Column 2");
   while (1)                // infinite loop.
   {
   }
}
 

الشكل التالى يبين المحاكاة :



Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأربعاء يونيو 21, 2017 11:26 am

كتابة القيم العددية Printing numeric values :
طباعة القيم العددية أمر حيوى فى  العديد من التطبيقات . على سبيل المثال عندما تريد عرض حالة التغير لحساس مثل درجة الحرارة أو الرطوبة أو الضغط أو أى جهاز آخر يتم التعامل معه .
لتحقيق هذا الهدف يمكن استخدام دوال التحويل الجاهزة والموجودة ضمن المترجم ميكروسى . يمكنك استخدام مكتبة التحويلات  Conversions ، هذه المكتبة بها دوال تقوم بتحويل القيم العددية إلى سلسلة .
عندما يتطلب الأمر عرض قيمة لعدد صحيح يتم استخدام الدالة :

الكود:
IntToStr (int input, char *output) ;

هذه الدالة تقوم بتحويل العدد الصحيح نوع signed integer إلى سلسلة string . سلسلة الخرج يكون لها عرض ثابت 7 أحرف بما فى ذلك حرف الانتهاء (نهاية السلسلة) . سلسلة الخرج تكون بمحازاة اليمين والأماكن المتبقية جهة اليسار (إن وجدت) تملء بفراغات .    
هذه الدالة لها بارامتران هما :  input وهو قيمة العدد الصحيح المراد عرضه ، و output والذى يشير إلى متغير لسلسلة نصية والذى تريد وضع نتيجة تحويل القيمة العددية input إلى سلسلة نصية فيه .
يجب إعلان السلسلة المستهدفة لتكون بطول 7  أحرف على الأقل .
لفهم هذا التحويل راقب وحلل المثال التالى :


الكود:
void main (void)
{
 int Integer = 123; // Declaration of an integer variable with initial value 123.
 char Text [20]; // String data printing , at least 7 characters in length.
 Lcd_init (); // Start the LCD.
 IntToStr (Integer, Text); // function that does the conversion.
 Lcd_Out_Cp (Text) ; // print text on the LCD screen.
 while (1) // infinite loop.
 {
 }
}


البرنامج :

الكود:
// IntToStr (int input, char *output) ;
// Converts input signed integer number to a string.
// Define 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 connection definition

void main (void)
{
 int Integer = 123; // Declaration of an integer variable with initial value 123.
 char Text [20]; // String data printing , at least 7 characters in length.
 Lcd_init (); // Start the LCD.
 IntToStr (Integer, Text); // function that does the conversion.
 Lcd_Out_Cp (Text) ; // print text on the LCD screen.
 while (1) // infinite loop.
 {
 }
}

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




يمكن طباعة الأعداد الحقيقية ذات العلامة العشرية باستخدام الدالة :

الكود:
FloatToStr (float FNUM, char * str);  

مبدأ عمل هذه الدالة مماثل للدالة السابقة .
ملحوظة :
سوف يتم بتر (اقتطاع) العدد float إلى السبع أرقام ذات الأهمية القصوى قبل التحويل .
يجب إعلان السلسلة المستهدفة لتكون بطول  14 حرف على الأقل .
مثال :

الكود:
float ff1 = -374.2;
float ff2 = 123.456789;
float ff3 = 0.000001234;
char txt[15];
...
FloatToStr(ff1, txt);  // txt is "-374.2"
FloatToStr(ff2, txt);  // txt is "123.4567"
FloatToStr(ff3, txt);  // txt is "1.234e-6"

لفهم هذه الدالة راقب وحلل المثال التالى :

الكود:

void main (void)
{
 int Integer = 123;   // Declaration of an integer variable with initial value 123.
 float Decimnal = 12.76543; // Declaring a variable with decimal point
 // initialized to 12.76543.
 char Text  [20]; // String data printing.
 Lcd_init (); // Start the LCD.
 IntToStr (Integer, Text); // Function that makes the whole conversion.
 Lcd_Out (1,1, Text); // print text on the LCD screen.
 FloatToStr (Decimnal, Text); // function that does the conversion decimal.
 Lcd_Out (2,1, Text); // print text on the LCD screen.
 while (1) // infinite loop.
 {
 }
}

البرنامج :

الكود:

// FloatToStr (float FNUM, char * str);
// Converts a floating point number to a string.
// Define 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 connection definition

void main (void)
{
 int Integer = 123;   // Declaration of an integer variable with initial value 123.
 float Decimnal = 12.76543; // Declaring a variable with decimal point
 // initialized to 12.76543.
 char Text  [20]; // String data printing.
 Lcd_init (); // Start the LCD.
 IntToStr (Integer, Text); // Function that makes the whole conversion.
 Lcd_Out (1,1, Text); // print text on the LCD screen.
 FloatToStr (Decimnal, Text); // function that does the conversion decimal.
 Lcd_Out (2,1, Text); // print text on the LCD screen.
 while (1) // infinite loop.
 {
 }
}
 


الشكل التالى يبين نتيجة المحاكاة :



نفس العملية يمكن تنفيذها على الأنواع الأخرى للمتغيرات مثل :

• فى حالة المتغير نوع  unsigned short :

الكود:
ByteToStr(unsigned short input, char *output);

تقوم هذه الدالة بتحويل "بايت" الدخل input إلى السلسلة ouput . السلسلة output  يكون لها عرض ثابت 4 حروف بما فى ذلك حرف الانتهاء . السلسلة output تكون بمحازاة اليمين والأماكن المتبقية على اليسار (إن وجدت) تملء بفراغات . إعلان السلسلة المستهدفة يجب ألا يقل طولها عن 4 أحرف .
مثال :

الكود:
unsigned short t = 24;
char txt[4];
...
ByteToStr(t, txt);  // txt is " 24" (one blank here)


• فى حالة المتغير (signed) short (int) أو short نستخدم الدالة :

الكود:
ShortToStr (short input, char * output);

تقوم هذه الدالة بتحويل الدخل input إلى السلسلة ouput . السلسلة output  يكون لها عرض ثابت 5 حروف بما فى ذلك حرف الانتهاء . السلسلة output تكون بمحازاة اليمين والأماكن المتبقية على اليسار (إن وجدت) تملء بفراغات . إعلان السلسلة المستهدفة يجب ألا يقل طولها عن 5 أحرف .
مثال :

الكود:
short t = -24;
char txt[5];
...
ShortToStr(t, txt);  // txt is " -24" (one blank here)


وفى حالة المتغير unsigned  int  نستخدم الدالة :

الكود:
WordToStr (unsigned int input, char * output);

تقوم هذه الدالة بتحويل الدخل input إلى السلسلة ouput . السلسلة output  يكون لها عرض ثابت 6 حروف بما فى ذلك حرف الانتهاء . السلسلة output تكون بمحازاة اليمين والأماكن المتبقية على اليسار (إن وجدت) تملء بفراغات . إعلان السلسلة المستهدفة يجب ألا يقل طولها عن 6 أحرف .
مثال :

الكود:
unsigned t = 437;
char txt[6];
...
WordToStr(t, txt);  // txt is "  437" (two blanks here)

• فى حالة المتغير Long نستخدم الدالة :

الكود:
LongToStr (long input, char * output);

تقوم هذه الدالة بتحويل الدخل input إلى السلسلة ouput . السلسلة output  يكون لها عرض ثابت 12 حروف بما فى ذلك حرف الانتهاء . السلسلة output تكون بمحازاة اليمين والأماكن المتبقية على اليسار (إن وجدت) تملء بفراغات . إعلان السلسلة المستهدفة يجب ألا يقل طولها عن 12 أحرف .
مثال :

الكود:
long jj = -3700000;
char txt[12];
...
LongToStr(jj, txt);
// txt is "   -3700000" (three blanks here)

طريقة تحويل العدد الصحيح unsigned int ، رقم تلو الآخر إلى سلسة ، حرف تلو الآخر :
بالرجوع إلى جدول كود أسكى نجد أن كل حرف من أحرفه يقابله قيمة عددية معينة ، فحرف الصفر ‘0’ يقابلة العدد 48 ، وحرف الواحد ‘1’ يقابلة العدد 49(1+48) والحرف اثنين ‘2’ يقابله العدد 50(2+48)  وهكذا ، من ثم يمكن استنتاج أنه لتحويل أى رقم إلى حرف كود أسكى المناظر يتم إضافة القيمة العددية 48 . بعبارة أخرى ، 0+48=’0’ ، و 1+48=’1’ و 2+48=’2’ وهكذا .
مثال :
تتبع الخطوات التالية :  
• إعلان متغير نوع  unsigned int باسم number وإسناد قيمة ابتدائية له هى الصفر وهذا السجل سوف يحتوى على العدد المطلوب عرضه (قبل تحويله إلى كود أسكى) .
• الإعلان عن متغير بالإشارة إليه بالطريقة *text  وهو عبارة عن نص مكون من أربعة خانات وإسناد قيمة أصفار كقيمة ابتدائية وهو عبارة عن مصفوفة صف بها 4 عناصر .

الكود:
unsigned int number = 0; // Integer number
char *text = "0000"; // Pointer to string

• إنشاء دالة باسم Display تحتوى على تقسيم (إستخلاص) محتويات السجل   numberإلى أربعة خانات (أرقام) وتحويل كل خانة إلى كود أسكى المناسب للعرض على وحدة العرض LCD حيث يتم :
# استخلاص قيمة رقم خانة الآلاف بقسمة العدد number على1000    ويضاف إلى النتيجة العدد 48 لتحويله إلى كود أسكى وحفظ النتيجة كأول عنصر من عناصر المصفوفة text[0]  .
# استخلاص قيمة رقم خانة المئات بقسمة العدد number على 100 ثم إيجاد باقى خارج قسمة الناتج على 10 والنتيجة النهائية يتم تحويلها إلى كود أسكى بإضافة 48 وحفظ النتيجة كثانى عنصر من عناصر المصفوفة
text[1]  .
# استخلاص قيمة رقم خانة العشرات بقسمة العدد number على 10 ثم إيجاد باقى خارج قسمة الناتج على 10 والنتيجة النهائية يتم تحويلها إلى كود أسكى بإضافة 48 وحفظ النتيجة كثالث عنصر من عناصر المصفوفة
text[2]  .
# استخلاص قيمة رقم خانة الآحاد بإيجاد باقى خارج قسمة العدد number على 10 والنتيجة يتم تحويلها إلى كود أسكى بإضافة 48 وحفظ النتيجة كرابع عنصر من عناصر المصفوفة text[3]  .
#  وأخير يمكن عرض هذه المصفوفة على وحدة العرض LCD ، على سبيل المثال ، فى الصف الثانى بدءا من العامود السابع كما يلى :  

الكود:
void Display ()   // define display_init;
{                    
 text[0] = number/1000 + 48;           // thousands digit, ASCII
 text[1] = (number/100)%10 +48;         // hundreds digit, ASCII  
 text[2] = (number/10)%10 + 48;       // tens digit ASCII
 text[3] = number%10 +48;               // unit digit ASCII;
 Lcd_Out(2,7, text);                     // display on LCD from Row 2, character 7
}

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأربعاء يونيو 21, 2017 11:33 am

تدريب رقم 1 : ربط وحدة العرض Interfacing a character LCD
الوصف
وحدات العرض LCD التى تعتمد على المتحكم HD4480 منتشرة لرخص سعرها ولأنه يمكنها عرض الحروف . علاوة على أنها من السهل ربطها مع الميكروكونترولر ومعظم المترجمات تتضمن مكتبات لروتينات تخصها .
سوف نستعرض ربط هذه الوحدة مع الميكروكونترولر PIC16F628A . يحتاج الربط إلى 6 خطوط مداخل / مخارج من الميكروكونترولر ، 4 خطوط للبيانات و 2 خط للتحكم . سوف نعرض السلسلة النصية التالية وهى تومض blinking كاختبار للربط :
“Welcome to ………” .
الدائرة الكهربية :
سوف يتم نقل البيانات بين الميكروكونترولر ووحدة LCD فى نظام 4-bit . الطرف (5) R/W لوحدة LCD يوصل بالأرضى بصفة دائمة لعدم وجود قراءة من وحدة LCD . الأطراف RB4-RB7 تستخدم كخطوط للبيانات . خطوط التحكم RS و E يتم توصيلها بالأطراف RB2 و RB3 . لذلك فإننا نستخدم 6 أطراف للربط بين الميكروكونترولر ووحدة LCD .



البرنامج
خطوط البيانات والتحكم لوحدة LCD تستخدم المنفذ PORTB لذلك يجب تعريف أطرافه كمخارج (TRISB=0) . برمجة وحدة LCD التى تعتمد على المتحكم HD44780 لها خطوات معقدة بعض الشىء لأنها تتطلب توقيت دقيق وتسلسل مناسب لمختلف إشارات التحكم والأوامر . لكن لحسن الحظ فإن المترجم MikroC Pro for PIC يمتلك فى بنائه الداخلى مكتبة دوال للاتصال مع وحدة العرض LCD القياسية التى تعتمد على المتحكم HD44780 باستخدام نظام
4-bit . هذه المكتبة تجعل البرمجة سهلة للغاية . فبل استخدام الدوال الداخلية لوحدة LCD يجب تعريف أطراف التوصيل بين وحدة LCD والميكروكونترولر .
البرنامج :

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

// Define Messages
 char message1[] = "Welcome to";
 char message2[] = "Eng.F.Abdelaziz";

void main()
{
   
            TRISB = 0;          // PORTB All Outputs

Lcd_Init();                                // Initialize LCD
do
{

  Lcd_Cmd(_LCD_CLEAR);               // CLEAR display
  Lcd_Cmd(_LCD_CURSOR_OFF);           // Cursor off
  Lcd_Out(1,4,message1);                  // Write message1 in 1st row
  Lcd_Out(2,1,message2);                // Write message2 in 2nd row
  Delay_ms(1000);                            // Wait for 1 sec
  Lcd_Cmd(_LCD_CLEAR);          // Clear display
  Delay_ms(1000);          // Wait for 1 sec

  } while(1);                     // Infinite Loop
}
 

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأربعاء يونيو 21, 2017 11:39 am

تدريب رقم 2 : تحريك الرسائل .
الدائرة الكهربية :



البرنامج :
الكود:
 
// Define 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 connection definition

char  txt1[] = "Eng.F. Abdelaziz" ;       
char txt2[] = "EasyPIC";
char txt3[] = "Lcd4bit";
char txt4[] = "example";

char i;                                    // Loop variable

void Move_Delay() {                  // Function used for text moving
  Delay_ms(500);                    // You can change the moving speed here
}
void main(){

 

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


  Lcd_Out(1,6,txt3);                // Write text in first row
  Lcd_Out(2,6,txt4);                // Write text in second row
  Delay_ms(2000);

  Lcd_Cmd(_LCD_CLEAR);              // Clear display
  Lcd_Out(1,1,txt1);                // Write text in first row
  Lcd_Out(2,5,txt2);                // Write text in second row


  Delay_ms(2000);


  // Moving text
  for(i=0; i<4; i++) {              // Move text to the right 4 times
    Lcd_Cmd(_LCD_SHIFT_RIGHT);
    Move_Delay();
  }


  while(1) {                        // Endless loop
    for(i=0; i<8; i++) {            // Move text to the left 8 times
      Lcd_Cmd(_LCD_SHIFT_LEFT);
      Move_Delay();
    }

    for(i=0; i<8; i++) {            // Move text to the right 8 times
      Lcd_Cmd(_LCD_SHIFT_RIGHT);
      Move_Delay();
    }
  }
}

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأربعاء يونيو 21, 2017 11:56 am

مشروع عد وعرض ومعالجة عدد الأشياء تصاعديا وتنازليا باستخدام PIC16F628 وLCD
يتم أستلام وعد النبضات من مدخلين حيث يخصص المدخل الأول RA0 لتزايد العداد والمدخل الثانى RA1 لتناقص العداد ويتم عرض الفرق بينهما على وحدة العرض LCD كعدد من 0000 إلى 9999 .
الدائرة الكهربية :


البرنامج :

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

char Message1[]="COUNTER";      // Message for line1
unsigned int number = 0;

char *text = "0000";

void Display()              // define display_init
{
 text[0] = number/1000 + 48;             // thousands digit
 text[1] = (number/100)%10 +48;          // hundreds digit
 text[2] = (number/10)%10 + 48;           // tens digit
 text[3] = number%10 +48;                 // unit digit
 Lcd_Out(2,7, text);                         // display on LCD from column 2, character 7
}

bit oldstate1;
bit oldstate2;

void main()                            // main;
{
 CMCON = 7;                  // turn off analogue comparator and make PORTA to digital I/O
 TRISA0_bit = 1;                        // make PORT RA0 as input for button
 TRISA1_bit = 1;                        // make PORT RA1 as input for button
 TRISB = 0;                            // Set PORTB direction to be output;
 PORTB = 0;                           
 Lcd_init();                            // LCD Initialization
 Lcd_cmd(_LCD_CLEAR);                  // Clear LCD
 Lcd_cmd(_LCD_CURSOR_OFF);              // Cursor mode off
 Lcd_out(1,2,Message1);               

 do{

if (PORTA.F0==0) {              // Detect logical 0
delay_ms(100);
      oldstate1 = 1;                              // Update flag
    }
    if (oldstate1 && PORTA.F0==1 ) {  // Detect zero-to-one transition
        Delay_ms(100);  //; If button is depressed, delay 0,1s and increment "number" with 1
    number = number +1;
      oldstate1 = 0;                              // Reset flag
    }


        if (PORTA.F1==0) {              // Detect logical 0
delay_ms(100);

        oldstate2 = 1;                              // Update flag
}

if (oldstate2 && PORTA.F1==1 ) {  // Detect zero-to-one transition              Delay_ms(100);    // If button is depressed, delay 0,1s and decrement "number" with 1
          number = number -1;

oldstate2 = 0;                              // Reset flag
                          }
    if (number > 9999)                // if it's more than 9999 go to 0
    number = 0;
    Display();                    // call display()

if(number>10) PORTB.B0=1;
else  PORTB.B0=0;

if(number>20) PORTB.B1=1;
else  PORTB.B1=0;
    } while(1);                        // infinite loop;
 }

 


فى هذا البرنامج يمكن إجراء أى عمليات رياضية أو منطقية على محتوى سجل المتغير number على سبيل المثال تشغيل خرج RB0 عندما يزداد العدد عن 10 (كمثال) وأيضا تشغيل مخرج آخر عندما يزداد العدد عن 20 وهكذا .

تعديل دالة العرض :

الكود:

void Display()              // define display_init
{
 char text [7] ;
  IntToStr(number, text);
 Lcd_Out(2,7,text);                        // display on LCD from column 2, character 7
}

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأربعاء يونيو 21, 2017 12:46 pm

الحروف المخصصة (التفصيل) custom بشاشة LCD والمترجم ميكروسى برو :
وحدات عرض الحروف LCD عادة ما تستخدم متحكمات متوافقة مع المتحكم HD44780 ، وهى تسمح لنا بتعريف 8 حروف مخصصة بالإضافة إلى الحروف القياسية المبرمجة مسبقا . هذه الوحدات تحتوى على ثلاثة أنواع من الذاكرة وهى :
• ذاكرة مولد الحرف الثابتة CGROM – Character Generator ROM : وهى تحتفظ بنماذج 5x8 أو 5x10 نقطة للحروف المعرفة مسبقا فى وحدة LCD . هذه الذاكرة يمكن أن تولد 208 نموذح حرف 5x8 نقطة و 32 نموذج حرف 5x10 نقطة .
• ذاكرة عرض البيانات DDRAM – Display Data RAM : وهذه هى الذاكرة التى تحتفظ ببيانات الحرف الذى يتم عرضه حاليا على شاشة LCD . حجم هذه الذاكرة 80×8 bits أى 80 حرف .
• ذاكرة مولد الحرف المتغيرة CGRAM – Character Generator RAM : تعمل هذه الذاكرة بشكل يشبة الذاكرة CGROM ولكن نظرا لأنها من نوغ RAM فإنه يمكننا تعديل بياناتها فى أى وقت . ومن ثم يمكننا تخزين نماذج الحروف المخصصة بواسطتنا فى هذه الذاكرة من خلال البرنامج . يمكننا تخزين حتى 8 نماذج حروف 5x8 نقطة أو حتى 4 نماذج حرف 5x10 نقطة فى هذه الذاكرة .
إنشاء حروفك الخاصة :
وحدات عرض الحروف LCD لديها القدرة على تخزين حتى 8 حروف مصممة بواسطة المبرمج . قيم أسكى للحروف المصممة بالمستخدم تناظر القيم الرقمية من 0 إلى 7 .
على سبيل المثال , إذا رغبت فى طباعة أول حرف مصمم بواسطة المستخدم يتم ذلك عن طريق استخدام دوال طباعة الحروف كما يلى : Lcd_Chr_Cp (0); أو Lcd_Chr(1,1,0); . يتم تخزين الأحرف التى ينشؤها المستخدم فى ذاكرة RAM لشاشة وحدة العرض LCD ولهذا السبب يجب إعادة برمجتها فى كل مرة تقوم فيها ببدء LCD .
الحروف هى مجموعة من القيم الثنائية تشكل صورة نقطية ، والنتيجة هى صورة تعرض على الشاشة بدقة
5 x 7 pixels .
تحرير وبرمجة هذه البيانات هو مضيعة للوقت ، لكن المترجم ميكروسى برو يوجد ضمن أدواته محرر للحروف لتصميم الحروف بمعرفة المبرمج . فى هذا المحرر البسيط يتم تحرير حرف الصورة النقطية وتوليد كود لغة السى اللازم لتحديد الحرف على الشاشة . والخلاصة أنه يتم تحرير الحرف ثم نسخ ولصق كود المصدر الخاص به فى برنامج المشروع .
إظهار هذا المحرر يتم عن طريق قائمة الأدوات Tools ثم الخيار Custom Character LCD .



الشكل التالى يبين نافذة هذا المحرر :




فى هذا المحرر يقوم المستخدم بالنقر على المربعات (النقط) التى تشكل الحرف ، يتم اختيار قيمة أسكى التى تخصص للحرف من خلال مربع الاختيارChar: . هذه القيمة يجب أن تقع بين 0 و 7 . يتم إنهاء هذه العملية بالضغط على الزر
Generate Codeونسخ هذاالكود لاستخدامه فى البرنامج .
الشكل التالى يبين المحرر عند تحرير حرف أسكى وتخصيص الصفر له :



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

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

 // Function to store in LCD RAM memory
// Constants created by the character editor, it contains the character bitmap.
 const char character [] = {17,14,21,14,31,4,27,0};
 void CustomChar (char pos_row , char pos_char)
 {
 char i;
 LCD_Cmd(64); // address character 0.
 for (i=0;i<=7;i++) LCD_Chr_Cp(character[i]);// Loop to save the bitmap.
 LCD_Cmd (_LCD_RETURN_HOME);// For practical purposes, this feature can be ignored.
 LCD_Chr(pos_row,pos_char,0); // Impression ASCII code 0.
 }
 void main (void)
 {
 Lcd_init(); // Start the LCD.
 CustomChar (1,1);// Print the character 0.
 while(1) // infinite loop.
 {
 }
 }

بعد الترجمة والمحاكاة نحصل على النتيجة التالية :




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

الكود:
 // Declaring Constants represent bitmaps,
// Animate a FIGs. These are the result code character editor
// MikroC PRO.
const char Fig1 [] = {17,14,21,14,31,4,27,0};    // Start CGRAM address 64 (Char=8 bit).
const char Fig2 [] = {17,14,21,14,31,4,10,0};    // start address 72(=64+8).
const char Fig3 [] = {17,14,21,14,31,21,10,0};    // start address 80(=72+8).
const char Fig4 [] = {24,28,30,31,30,28,24,0};    // start address 88(=80+8).
 
// Define 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 connection definition


 // Function to save Declamation characters in RAM.
 // This function is designed by the developer.
 void Lcd_RAM_Car  (char IntDir ,  const char * Map)    // RAM Address & Char. Map
 {
    char i;
    LCD_Cmd (IntDir);             // Start RAM address.
    // Loop to save the map in the LCD RAM.
    for (i= 0; i <8; i ++) LCD_Chr_Cp (Map [i]);
 }

 
void main (void)
 {
    Lcd_init ();       // Start the LCD.

    Lcd_RAM_Car (64, Fig1);   // Creat & Store the character 1 in first RAM address >>64
    Lcd_RAM_Car (72, Fig2);   // Creat &Store the character 2 ( 72=64+8)
    Lcd_RAM_Car (80, Fig3);   // Creat &Store the character 3 ( 80=72+8)
    Lcd_RAM_Car (88, Fig4);   // Creat &Store the character 4 ( 88=80+8)

    LCD_Chr (1, 1, 0);      // Finally : Print the character Fig1.(0 in ASCII) in pos ( 1,1)
    LCD_Chr (1, 2, 1);       // Print the character Fig2.(1 in ASCII) in pos ( 1,2)
    LCD_Chr (1, 3, 2);       // Print the character Fig3.(2 in ASCII) in pos ( 1,3)
    LCD_Chr (1, 4, 3);       // Print the character Fig4.(3 in ASCII)  in pos (1,4)

    while (1) // infinite loop.
    {
    }
 }

بعد الترجمة والمحاكاة نحصل على النتيجة التالية :



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

الكود:
  Lcd_Cmd (char out_char)  ; 

والتى تدخل ضمن أوامر الإعداد ، باستخدام البارامتر out_char .
لتغيير المؤشر بآخر غير ممتلىء فى شكل شرطة يتم استخدام الدالة :

الكود:
Lcd_Cmd (_LCD_UNDERLINE_ON) ;

ولتفعيل وميض المؤشر نستخدم الدالة :

الكود:
Lcd_Cmd (_LCD_BLINK_CURSOR_ON);

ولعدم إظهار المؤشر نستخدم الدالة :

الكود:
 Lcd_Cmd (_LCD_CURSOR_OFF);


Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأربعاء يونيو 21, 2017 12:56 pm

تدريب :





الخطوات :
• تحديد حجم الخط Font size وليكن 5x7 .
• تحديد عنوان الذاكرة CGRAM address أى من 0 إلى 7 .
• تصميم حرفك الخاص بالنقر فوق مربعات شكل نموذج النقط .
• بعد ذلك يتم النقر على الزر Generate Code ، ثم نسخ الكود .
سوف تحصل على دالة لحفظ وعرض الحرف الخاص على وحدة LCD . عن طريق تغيير عنوان الذاكرة CGRAM يمكنك تخزين حتى 8 حروف خاصة فى ذاكرة وحدة LCD . فيما يلى كود البرنامج المعدل والذى سوف يخزن ويعرض 8 حروف خاصة على وحدة LCD .

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

const char character0[] = {0,0,10,31,31,14,4,0};
const char character1[] = {14,27,17,17,17,17,31,0};
const char character2[] = {14,27,17,17,17,31,31,0};
const char character3[] = {14,27,17,17,31,31,31,0};
const char character4[] = {14,27,17,31,31,31,31,0};
const char character5[] = {14,31,31,31,31,31,31,0};
const char character6[] = {0,4,2,31,2,4,0,0};
const char character7[] = {0,0,14,17,17,10,27,0};

void CustomChar0() {
  char i;
  Lcd_Cmd(64);// RAM address for the custom char. Next custom char it to be in RAM address 72 and so on.
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character0[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar1() {
  char i;
  Lcd_Cmd(72);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character1[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar2() {
  char i;
  Lcd_Cmd(80);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character2[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar3() {
  char i;
  Lcd_Cmd(88);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character3[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar4() {
  char i;
  Lcd_Cmd(96);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character4[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar5() {
  char i;
  Lcd_Cmd(104);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character5[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar6() {
  char i;
  Lcd_Cmd(112);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character6[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void CustomChar7() {
  char i;
  Lcd_Cmd(120);
  for (i = 0; i<=7; i++) Lcd_Chr_CP(character7[i]);
  Lcd_Cmd(_LCD_RETURN_HOME);
}

void main()  {
  Lcd_Init(); // Initialize LCD

  Lcd_Cmd(_LCD_CLEAR); // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off

  //Send Custom Charactors to CGRAM
  CustomChar0();
  CustomChar1();
  CustomChar2();
  CustomChar3();
  CustomChar4();
  CustomChar5();
  CustomChar6();
  CustomChar7();
  //End

  //Display Custom Characters
  Lcd_Chr(1,1,0);
  Delay_ms(1000);
  Lcd_Chr(1,2,1);
  Delay_ms(1000);
  Lcd_Chr(1,3,2);
  Delay_ms(1000);
  Lcd_Chr(1,4,3);
  Delay_ms(1000);
  Lcd_Chr(1,5,4);
  Delay_ms(1000);
  Lcd_Chr(1,6,5);
  Delay_ms(1000);
  Lcd_Chr(1,7,6);
  Delay_ms(1000);
  Lcd_Chr(1,8,7);
  Delay_ms(1000);
}
 

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الجمعة يونيو 23, 2017 11:50 pm

استخدام مصفوفة لوحة المفاتيح matrix Using keyboards
تتطلب تطبيقات الميكروكونترولر فى بعض الحالات استخدام المفاتيح لإدخال البيانات العددية والوظائف وحتى حروف النصوص . الخيار الأكثر عمليا هو استخدام مصفوفة لوحة المفاتيح ، والتى تتكون من مفاتيح ضاغطة مرتبة فى صفوف rows وأعمدة columns ، لتقليل عدد التوصيلات الكهربائية . الشكل التالى يبين المظهر الطبيعى لمصفوفة لوحة مفاتيج 4X4 والدائرة المكافئة :



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

يحتوى مترجم الميكروسى برو على مكتبة للتحكم وقراءة لوحة المفاتيح 4X4 ، هذه المكتبة بها ثلاثة دوال مخصصة لهذا الغرض .



دوال المكتبة التى تسمح باستخدام لوحة المفاتيح 4X4 هى :
الدالة الأولى :

الكود:
 void Keypad_Init (void);

• تستخدم هذه الدالة لتهيئة (إعداد) لوحة المفاتيح للاستخدام إعتمادا على المنفذ المصمم لهذا الغرض والذى تم إعلانه مسبقا .
• هذه الدالة لا تعود بشىء void ، وتتطلب إعلان المنفذ المعد لتوصيلها بصيغة محددة كما فى المثال التالى :

الكود:
// Keypad module connections
char keypadPort at PORTD;
// End of keypad module connections
...
Keypad_Init();



الدالة الثانية :

الكود:
  char Keypad_Key_Press(void);
Reads the key from keypad when key gets pressed.

• تستخدم هذه الدالة فى قراءة المفتاح من لوحة المفاتيح عندما ستم الضغط على المفتاح .
• هذه الدالة تقوم بإرجاع (العودة) كود المفتاح الذى تم الضغط عليه كقيمة من 0 إلى 16 ، قيمة الصفر (0) تعنى أن لم يتم الضغط على أى مفتاح ، والقيم من (1) إلى (16) تمثل 16 مفتاح متاح أى تقوم على الفور بإرجاع حالة المفتاح فى كل مرة يتم استدعاؤها . هذه الدالة تتطلب تهيئة منفذ توصيل لوحة المفاتيح .
مثال :

الكود:
char kp;
...
kp = Keypad_Key_Press();


الدالة الأخيرة :

الكود:
  char Keypad_Key_Click(void);

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

الكود:
char kp;
...
kp = Keypad_Key_Click();

تدريب تمهيدى 1 :
لدراسة خواص لوحة المفاتيح ، سوف نستعرض مشروع جديد ببرنامج ISIS والذى يحتاج للأجهزة التالية : PIC16F877A, RES, BUTTON, LM016L . فقط يجب عليك إنشاء مشروع جديد بمترجم الميكروسى برو .
الشكل التالى يبين الدائرة الكهربية :



البرنامج التالى يقوم بقراءة لوحة المفاتيح وعرض نتيجة العودة على LCD . لهذا الهدف راقب وحلل البرنامج :


الكود:
// Declaration 4x4 keyboard port
char keypadPort at PORTC;

// Define pins for LCD.
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D4 at RB0_bit;
// Definition of TRIS registers for LCD.
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D7_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB0_bit;
void main (void)
{
   // Declaration of variables.
   unsigned short Key;
   char Text  [20];
   // Setup and initialization of PIC.
   Keypad_Init();                          // Initialize Keypad
   Lcd_init ();          // Initialize the LCD.
   Lcd_Cmd(_LCD_CLEAR);                    // Clear display
   Lcd_Cmd (_LCD_CURSOR_OFF);    // Turns off the cursor.
   Lcd_Out (1, 1, "Key");       // Print text.
   while (1)             // infinite loop.
   {
       Key = Keypad_Key_Press (); // It reads the keyboard and stores the result in key.
       ByteToStr (Key, Text);       // conversion from integer to text.
       Lcd_Out (2,1, Text);       // Display the value returned by the keyboard.
   }
}




المحاكاة : يمكنك مشاهدة القيم التى تعود عند الضغط على المفتاح ، الشكل التالى يبين أنه عند الضغط على المفتاح بالمسمى 8 فأن نتيجة العودة هى (10) وهى ترتيب المفتاح ، بينما عندما لا يكون هناك مفتاح مضغوط فتظهر قيمة العائد بصفر (0) .







لهذه الحالة المحددة بالمثال يتم مسح لوحة المفاتيح من اليسار إلى اليمين ومن أعلى إلى أسفل بدءا من المفتاح (1) ,إنتهاء بالمفتاح (D) . هذا يعنى أن عوائد دالة لوحة المفاتيح كما يلى :




تدريب تمهيدى 2 :
حتى هذه النقطة يمكنك قراءة لوحة المفاتيح كسلسلة من الأعداد ولكنها لا تكافىء المفتاح المضغوط ، لتصحيح هذا الوضع يجب تنفيذ دالة لفك شفرة القيم المعطاة بلوحة المفاتيح لكى تصبح حروف حقيقية لما تمثله المفاتيح . لهذا الهدف يتم عمل الدالة التالية عن طريق عبارة switch case لفك شفرة لوحة المفاتيح:

الكود:
 // Function to decode the keyboard.
char ReadKeyboard  (void)
{
// Switch case structure to assess the values returned
// by press keyboard.
   switch (Keypad_Key_Press ())
   {
      case 1: return ‘1’;
      case 2: return ‘2’;
      case 3: return ‘3’;
      case 4: return ‘A’;
      case 5: return ‘4"’;
      case 6: return ‘5’;
      case 7: return ‘6’;
      case 8: return ‘B’;
      case 9: return ‘7’;
      case 10: return ‘8’;
      case 11: return ‘9’;
      case 12: return ‘C’;
      case 13: return ‘*’;
      case 14: return ‘0’;
      case 15: return ‘#’;
      case 16: return ‘D’;
      default: return 0;    // button not pressed.
   }
}

برنامج هذا التطبيق يصبح كما يلى :


الكود:
// Declaration 4x4 keyboard port
 char keypadPort at PORTC;

 // Definition pins for LCD.
 sbit LCD_RS at RB4_bit;
 sbit LCD_EN at RB5_bit;
 sbit LCD_D7 at RB3_bit;
 sbit LCD_D6 at RB2_bit;
 sbit LCD_D5 at RB1_bit;
 sbit LCD_D4 at RB0_bit;
 // Definition of TRIS registers for LCD.
 sbit LCD_RS_Direction at TRISB4_bit;
 sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D7_Direction at TRISB3_bit;
 sbit LCD_D6_Direction at TRISB2_bit;
 sbit LCD_D5_Direction at TRISB1_bit;
 sbit LCD_D4_Direction at TRISB0_bit;
 // Function to decode the keyboard.
 char ReadKey (void)
 {
 // Switch case structure to assess the values ??returned
 // by press keyboard.
 switch (Keypad_Key_Press ())
 {
 case 1: return '1';
 case 2: return '2';
 case 3: return '3';
 case 4: return 'A';
 case 5: return '4';
 case 6: return '5';
 case 7: return '6';
 case 8: return 'B';
 case 9: return '7';
 case 10: return '8';
 case 11: return '9';
 case 12: return 'C';
 case 13: return '*';
 case 14: return '0';
 case 15: return '#';
 case 16: return 'D';
 default: return 0; // button not pressed.
 }
 }

void main (void)
 {
    // Declaration of variables.
    char key;
    // Setup and initialization of PIC.
   Keypad_Init();                          // Initialize Keypad
    Lcd_init ();          // Initialize the LCD.
   Lcd_Cmd(_LCD_CLEAR);                    // Clear display
    Lcd_Cmd (_LCD_CURSOR_OFF);    // Turns off the cursor.
    Lcd_Out (1, 1, "key");       // Print text.
    while (1)             // infinite loop.
    {
        Key = ReadKey ();       // It reads the keyboard and its result is stored in key.
        Lcd_Chr (2,1, key);       // Display the value returned by the keyboard.
    }
 }

بمجرد التحرير يتم الترجمة والمحاكاة حيث يعرض على الشاشة الحرف المقابل للمفتاح المضغوط بلوحة المفاتيح كما فى الشكل التالى :





Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في السبت يونيو 24, 2017 11:55 am

تدريب تمهيدى 3 ، مثال مكتبة keypad بالمترجم ميكروسى برو :
فيما يلى مثال بسيط على استخدام مكتبة لوحة المفاتيح ، وهو يدعم لوحة المفاتيح مع من 1 إلى 4 صف و من 1 إلى 4 عامود . عائد الدالة Keypad_Key_Click() هو عدد فى المدى من 1 إلى 16 . فى هذا المثال يتم تحويل عائد الدالة إلى كود أسكى (0….9,A…F) والعرض على وحدة العرض LCD ، فى الصف الأول . بالإضافة إلى عرض عدد مرات الضغط على المفتاح ، فى الصف الثانى لوحدة العرض LCD ، من خلال متغير العداد بسعة بايت .

البرنامج :

الكود:
unsigned short kp, cnt, oldstate = 0;
char txt[6];

// Keypad module connections
char  keypadPort at PORTC;
// End Keypad module connections

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

void main() {
  cnt = 0;                                      // Reset counter
  Keypad_Init();                                 // Initialize Keypad                             
  Lcd_Init();                                   // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                       // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);                // Cursor off
  Lcd_Out(1, 1, "Key  :");                      // Write message text on LCD
  Lcd_Out(2, 1, "Times:");

  do {
    kp = 0;                                      // Reset key code variable

    // Wait for key to be pressed and released
       do
        // kp = Keypad_Key_Press();          // Store key code in kp variable
         kp = Keypad_Key_Click();            // Store key code in kp variable
       while (!kp);
  // Prepare value for output, transform key to it's ASCII value
    switch (kp) {
      case  1: kp = 49; break; // 1       
      case  2: kp = 50; break; // 2
      case  3: kp = 51; break; // 3
      case  4: kp = 65; break; // A
      case  5: kp = 52; break; // 4
      case  6: kp = 53; break; // 5
      case  7: kp = 54; break; // 6
      case  8: kp = 66; break; // B       
      case  9: kp = 55; break; // 7
      case 10: kp = 56; break; // 8
      case 11: kp = 57; break; // 9
      case 12: kp = 67; break; // C
      case 13: kp = 42; break; // *
      case 14: kp = 48; break; // 0
      case 15: kp = 35; break; // #
      case 16: kp = 68; break; // D

    }

    if (kp != oldstate) {                  // Pressed key differs from previous
      cnt = 1;
      oldstate = kp;
      }
    else {                                // Pressed key is same as previous
      cnt++;
      }

    Lcd_Chr(1, 10, kp);                    // Print key ASCII value on LCD

    if (cnt == 255) {                      // If counter varialble overflow
      cnt = 0;
      Lcd_Out(2, 10, "  ");
      }

    WordToStr(cnt, txt);                  // Transform counter value to string
    Lcd_Out(2, 10, txt);                  // Display counter value on LCD
  } while (1);
}
 

النتيجة :



Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في السبت يونيو 24, 2017 1:30 pm

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



لوحة المفاتيح الرقمية تستخدم فى كثير من المجالات ، من أنظمة الأمان وحتى التليفونات المحمولة . فى هذا المشروع سوف نستخدم لوحة مفاتيح 4x3 لإدخال كلمة المرور password ، إذا كانت كلمة المرور صواب يتم فتح القفل الإلكترونى .
الدائرة الكهربية :




فى هذا المشروع سوف نستخدم الميكروكونترولر PIC16F877A ، والذى يعمل على تردد 4MHz . فى البداية يطلب إدخال كلمة المرور والتى تم تحديدها فى البرنامج مسبقا ، وهى “2345” والتى تم حفظها فى مصفوفة السلسلة pass . إذا تطابقت كلمة المرور التى يقوم المستخدم بإدخالها مع كلمة المرور المحددة مسبقا سوف يتم تشغيل ريلاى لمدة 10 ثوانى ، أما إذا لم يكن هناك تطابق بينهما ، غير صواب ، يتم طلب إدخال كلمة المرور مرة أخرى . البرنامج بسيط ويمكن فهمه بسهولة . يجدر ملاحظة أنه قد تم استخدام عبارة switch-case هنا لتحويل القيم من لوحة المفاتيح (1,2,3….16) إلى مكافىء كود أسكى حتى نتمكن من عرضها على وحدة العرض LCD ، هناك طرق أخرى لتنفيذ هذا التحويل . أيضا لعلك لاحظت ترتيب أطراف التوصيل ، يجب توصيل الأعمدة بالأطراف (0,1,2,3) للمنفذ المستخدم ، وتوصيل الصفوف بالأطراف (4,5,6,7) لنفس المنفذ ، فى حالة لوحة المفاتيح 4X3 لا يوجد عامود رابع ويترك طرفه بدون توصيل .

البرنامج :

الكود:
// LCD 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;
//=================================
char password[4],i=0,j=7,kp=0;
const char pass[5]="2345"; //The password was set at 2345.
char  keypadPort at PORTD; // The keypad will be connected to the PORTD.

void main() {
trisb.f0=0;
portb.f0=0;

Keypad_Init();                          // Keypad Set up.
Lcd_Init();                              // LCD Set up .

Lcd_Cmd(_LCD_CLEAR);                    // Clear LCD
Lcd_Cmd(_LCD_CURSOR_OFF);                // Close the cursor.
Lcd_out(1,1,"Enter Password:");
lcd_out(2,7,"____");
while(1)
{
kp=0;
   while(kp==0)         // Continuously scans keys when no key is pressed.
   {
      kp=Keypad_Key_Click();   //Press the keypad to get the value.
      delay_ms(10);         // 10ms delay .
   }

   switch (kp) {   // ASCII conversion is done (eg ASCII code 49 which corresponds to 1 character).
      case  1: kp = 49; break; // 1
      case  2: kp = 50; break; // 2
      case  3: kp = 51; break; // 3
      //case  4: kp = 65; break; // A      
      case  5: kp = 52; break; // 4
      case  6: kp = 53; break; // 5
      case  7: kp = 54; break; // 6
      //case  8: kp = 66; break; // B
      case  9: kp = 55; break; // 7
      case 10: kp = 56; break; // 8
      case 11: kp = 57; break; // 9
      //case 12: kp = 67; break; // C
      case 13: kp = 42; break; // *
      case 14: kp = 48; break; // 0
      case 15: kp = 35; break; // #
      //case 16: kp = 68; break; // D
   }

   lcd_chr(2,j,'*');
   j++;
   if(j==11)j=7;
   
   password[i]=kp;
   i++;
   if(i==4)
   {
      i=0;
      if(password[0]==pass[0] && password[1]==pass[1] && password[2]==pass[2] && password[3]==pass[3])
      // If the password is correct, it will ON the relay for 10 seconds ...
      {
         portb.f0=1;
         
          Lcd_Cmd(_LCD_CLEAR);
         lcd_out(1,1,"Password is :");
         lcd_out(2,1,"correct!");
         delay_ms(10000);
         
         Lcd_Cmd(_LCD_CLEAR);                    // Clear LCD
         Lcd_out(1,1," Enter Password:");
         lcd_out(2,7,"____");
         portb.f0=0;
      }
      else              // If the password is wrong, ask for the password again ...
      {
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1," Wrong password!");
      portb.f7=0;
      delay_ms(2000);
      Lcd_out(1,1," Enter Password:");
      lcd_out(2,7,"____");
      }
   }
}
}
 

النتيجة :





Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في السبت يوليو 01, 2017 11:17 pm

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

الكود:
// for PIC16
unsigned short EEPROM_Read(unsigned short address);
// for PIC18
unsigned short EEPROM_Read(unsigned int address); 


• تستخدم هذه الدالة لقراءة وإرجاع البيانات من عنوان محدد بالبارامتر address . البارامتر address يعتمد على الميكروكونترولر ، من أجل العائلة PIC16 يكون من النوع short ( الذاكرة لا تتعدى 256 بايت) ، ومن أجل العائلة PIC18 يكون من النوع int ( الذاكرة تتعدى 256 بايت ) .
• هذه الدالة تعود ببايت byte من العنوان address المحدد .
• هذه الدالة تتطلب وجود موديول EEPROM داخلى .
• يجب ضمان تأخير لا يقل عن 20ms بين الاستخدام المتعاقب لدالة الكتابة ودالة القراءة . فعلى الرغم من أن الميكروكونترولر سوف يكتب القيمة الصحيحة من خلال دالة الكتابة ، إلا أن دالة القراءة قد تعود بنتائج غير محددة .
ملاحظة : العناوين فى المدى من 0x00 إلى 0xFF من أجل الأجهزة التى بها 256 بايت ، فى حين يكون فى المدى من 0x00 إلى 0x7F من أجل الأجهزة التى بها 128 بايت .

مثال :

الكود:
unsigned short take;
...
take = EEPROM_Read(0x3F);

دالة الكتابة إلى ذاكرة EEPROM :

الكود:
  // for PIC16
void EEPROM_Write(unsigned short address, unsigned short data);
// for PIC18
void EEPROM_Write(unsigned int address, unsigned short data);

• تستخدم هذه الدالة فى كتابة البيانات data إلى العنوان address . البارامتر address يعتمد الميكروكونترولر . كن حذرا حيث أن جميع المقاطعات سوف يتم تعطيلها خلال تنفيذ دالة الكتابة ( مسح بت عموم المقاطعة GIE بالسجل INTCON ) . سوف تقوم الدالة باسترجاع الحالة السابقة لهذه البت عند انتهائها .
• هذه الدالة لا تعود بأى بيانات .
• هذه الدالة تتطلب وجود موديول EEPROM داخلى .
• يجب ضمان تأخير لا يقل عن 20ms بين الاستخدام المتعاقب لدالة الكتابة ودالة القراءة . فعلى الرغم من أن الميكروكونترولر سوف يكتب القيمة الصحيحة من خلال دالة الكتابة ، إلا أن دالة القراءة قد تعود بنتائج غير محددة .
مثال :

الكود:
EEPROM_Write(0x32, 19);

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في السبت يوليو 01, 2017 11:34 pm

تدريب تمهيدى 1 :

الكود:
unsigned short data = 0xAA, address=0x00;

void main() {
PORTB = 0x00;
TRISB = 0x00;

//writes 0xAA into the location 0x00
EEprom_Write(address,data);

//insert 20 or 30 ms delay between every read and write cycle
Delay_ms(20);

// the following delay is just for making a feel
Delay_ms(1000);

//reads the data from 0x00 and send it to PORTB
PORTB = Eeprom_Read(address);
Delay_ms(1000);
 

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

الكود:
void main (void)
{
 // Configure ports.
 TRISB = 0;
 PORTB = 0;
 while (1) // infinite loop.
 {
 // Displays the value on port B
 // From address 0 of the EEPROM.
 PORTB =EEPROM_Read (0);
 // The if statement evaluates if the button is pressed.
 if (! PORTC.F0)
 {
 // Increase the value of port B.
 PORTB ++;
 // Store the new port value
 // At address 0 of the EERPOM.
 EEPROM_Write (0, PORTB);
 // Wait up to release.
 while (! PORTC.F0);
 }
 }
}
لمحاكاة هذا البرنامج يتم جلب العناصر التالية لبرنامج ISIS :
 

لمحاكاة هذا البرنامج يتم جلب العناصر التالية لبرنامج ISIS :
16F877A, IC, LED-RED, BUTTON .

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




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

تدريب تمهيدى 3 : مثال مكتبة EEPROM

الكود:
char ii;                                 // loop variable

void main(){
  
  PORTB = 0;
  PORTC = 0;
  PORTD = 0;

  TRISB = 0;
  TRISC = 0;
  TRISD = 0;
  
  for(ii = 0; ii < 32; ii++)             // Fill data buffer
    EEPROM_Write(0x80+ii, ii);           // Write data ii to address 0x80+ii

  EEPROM_Write(0x02,0xAA);               // Write some data 0xAA at address 0x02
  EEPROM_Write(0x50,0x55);               // Write some data 0x55 at address 0x50

  Delay_ms(1000);                         // Blink PORTB and PORTC LEDs
  PORTB = 0xFF;                           //   to indicate reading start
  PORTC = 0xFF;
  Delay_ms(1000);
  PORTB = 0x00;
  PORTC = 0x00;
  Delay_ms(1000);

  PORTB = EEPROM_Read(0x02);            // Read data from address 2 and display it on PORTB
  PORTC = EEPROM_Read(0x50);      // Read data from address 0x50 and display it on PORTC

  Delay_ms(1000);

  for(ii = 0; ii < 32; ii++) {           // Read 32 bytes block from address 0x80
    PORTD = EEPROM_Read(0x80+ii);        //   and display data on PORTD
    Delay_ms(250);
    }
}
 

تدريب تمهيدى 4 :
فى هذا التدريب نقوم بكتابة (00000001) إلى أول موقع ذاكرة EEPROM ، و (00000010) إلى ثانى موقع و (00000100) إلى ثالث موقع وهكذا على التتابع حتى (10000000) ، ثم بعد ذلك يتم القراءة المتتابغة لمحتويات هذه المواقع وإخراجها إلى المنفذ PORTC .  


الكود:
void main()
{
   unsigned int a, i;
   TRISC  = 0;
   do
   {
      for(i=0,a=1;i<8;i++)
      {
        EEPROM_Write(i, a);
        a = a<<1;
      }
      
      for(i=0;i<8;i++)
      {
         PORTC = EEPROM_Read(i);
         Delay_ms(1000);
      }
   }while(1);
}
 

Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الأحد يوليو 02, 2017 11:12 am

تدريب :
المرجع : http://embedded-lab.com/blog/lab-13-read-and-write-to-internal-eeprom/
فى هذا التدريب سوف نستعرض كيفية تنفيذ عمليات القراءة من والكتابة إلى الذاكرة الداخلية للميكروكونترولر PIC16F628A ، والذى يمتلك 128 بايت من ذاكرة البيانات نوع EEPROM بعناوين فى المدى من 00h إلى 7Fh .

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



البرنامج :
سوف نكتب برنامج لتطبيق صغير من أجل الميكروكونترولر PIC16F628A والذى يقوم بعمليات القراءة Read والكتابة Write والمسح Delete لمواقع ذاكرة EEPROM المختارة ( 00h إلى 0Fh ) .
• عند الضغط على المفتاح Read ، يتم قراءة معلومات 16 بايت المخزنة عند المواقع (العناوين) 00h-0Fh وعرضها على شاشة LCD .
• عند الضغط على المفتاح Write سوف يتم كتابة السلسلة ‘Embedded-Lab.com’ إلى هذه المواقع .
• عند الضغط على المفتاح Delete يتم استبدال القيم الموجودة فى هذه المواقع بأصفار .
ملحوظة :
القيم الافتراضية فى مواقع ذاكرة EEPROM ممسوحة erased تكون كلها FFh (255) . عند عرض هذه القيم على شاشة LCD تجعل جميع نقط الشاشة فعالة . ولذلك ، عندما تقرأ ذاكرة EEPROM لأول مرة ، حيث تكون فى حالة المسح ، سوف تقراء جميهعا FFh كما هو موضح بالشكل أدناه .





بمجرد أن تتم عملية الكتابة ، قم بفصل القدرة لعدة ثوانى ، ثم قم بإعادة توصيل القدرة مرة أخرى ، واضغط على مفتاح القراءة ، سوف ترى السلسلة Embedded-Lab.com ما زالت محفوظة داخل ذاكرة EEPROM .

الكود:
/* Project name:
    Use of internal EEPROM for storing information
 * Copyright:
    (c) Rajendra Bhatt, 2011.
 * Description:
    This code demonstrates how to perform basic Read and Write operations
    with the internal EEPROM of PIC16F628A.
    MCU:            PIC16F628A
    Oscillator:      XT, 4.0 MHz
*/
// LCD connections definitions
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_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 TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_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 connections definitions

// Other connections
sbit SW1 at RB0_bit;
sbit SW2 at RB1_bit;
sbit SW3 at RB2_bit;
/*
// String array to store 3 digit access code
char message1[] = "1.READ";
char message2[] = "2.WRITE";
char message3[] = "3.Delete";
char message4[] = "WRITE COMPLETED";
char message5[] = "Read Data";
char message6[] = "Data Deleted";
*/
char message7[] = "Embedded-Lab.com";
char Edata[] = "0000000000000000";
unsigned short  i ;
unsigned int ADD; // Start EEPROM Location
char temp;
void Delay2s(){
 Delay_ms(2000);
}

void Debounce(){
 Delay_ms(100);
}

void main() {
 PORTB = 0;
 PORTA = 0;
 TRISB = 0b00001111;
 TRISA = 0b00100000;
 CMCON=0x07;
 Lcd_Init();                        // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);              // Clear LCD
 Lcd_Cmd(_LCD_CURSOR_OFF);          // Turn cursor off
 Lcd_Out(1, 1, "Lab 13: Testing");
 Lcd_Out(2, 1, "internal EEPROM");
 Delay2s();
//=========================================
 start:
 Lcd_Cmd(_LCD_CLEAR);
 Lcd_Out(1,1, "1.READ");            // Write message1 in 1st row
 Lcd_Out(1,8, "2.WRITE");
 Lcd_Out(2,1, "3.Delete");
 do{

  // Read Operation
  if (!SW1) {
      Debounce();
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1, "Read Data");
      ADD = 0;
      for (i=0; i<16; i++) {
      temp = EEPROM_Read(ADD+i);
      Edata[i] = temp;
      }
      Lcd_Out(2,1,Edata);
      Delay2s();
      goto start;
  }
  // Write Operation
  if (!SW2) {
      Debounce();
      ADD = 0;
      for (i=0; i<16; i++) {
      temp = message7[i];
      EEPROM_Write(ADD+i,temp);
      }
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1, WRITE COMPLETED");
      Delay2s();
      goto start;
  }

  // Delete Operation
  if (!SW3) {
      Debounce();
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1, "Data Deleted");
      for (i=0; i<16; i++) {
      temp = '0';
      EEPROM_Write(ADD+i, temp);
      }
      Delay2s() ;
      goto start;
  }
 
 
 } while(1);
 
}
 

Admin
Admin

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

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

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

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

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

مشروع قفل باب رقمى باستخدام الميكروكونترولر PIC16F877A :

الغرض :
تطبيق على استخدام شاشة LCD و لوحة المفاتيح Keypad وذاكرة EEPROM الداخلية .

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



الوصف :
• لايوجد كلمة سر Password افتراضية ، ويوجد داخل البرنامج كلمة سر رئيسية master password وهى فى هذه الحالة (23456) ، على سبيل المثال ويمكن تغيرها وتغيير عدد الحروف من داخل البرنامج .
• فى بداية التشغيل يطلب منك الضغط على الزر * ، بعد الضغط على هذا الزر سوف يطلب منك إدخال كلمة السر ، عندئذ ينبغى عليك أن تقوم بإدخال كلمة السر الرئيسية متبوعة بالضغط على الزر # ، الذى يقوم مقام زر الإدخال Enter ، سوف تظهر لك رسالة تفيد إدخال رقم سرى جديد ، عندئذ يمكنك كتابة الرقم السرى الذى ترغب فيه ، بكتابة أربع أرقام و / أو حروف المتوفرة فى لوحة المفاتيح ثم الضغط على الزر # .
• إذا حدث خطأ فى كتابة رقم يمكنك إعادة الكتابة من جديد بالضغط على الزر * ليبدأ من جديد .
• بعد تحديد كلمة السر الجديدة يمكنك فتح وغلق الباب بإدخال الأربع أرقام ثم الضغط على الز # .
• يمكنك تغيير كلمة السر فى أى وقت بإدخال كلمة السر الرئيسية .
• كلمة السر سوف تظل محفوظة داخل ذاكرة EEPROM حتى بعد غياب القدرة .
• عند إدخال كلمة سر غير صالحة ، تظهر لك رسالة عدم السماح ACCESS DENIED .
• إذا تكرر إدخال كلمة سر غير صالحة لثلاثة محاولات ، عندئذ يعمل الإنذار وتظهر رسالة تحذير . بعد ذلك تنطلق إشارة التحذير عند كل محاولة غير صحيحة .



الكود:
 // Keypad module connections
char keypadPort at PORTD;
// End Keypad module connections
// 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 connection
//================================
unsigned short kp,i=0,cnt,j=0;
char input_PW[10] ,user_PW[4];
//================================
char msg1[] = ".. PROTECTED ..",msg2[] = "ENTER PASSWORD";
char msg3[] = "ACCESS GRANETED",msg4[] = "ACCESS DENIED";
char msg5[] = "Enter New Code",msg6[] = "**Done**" ;
char msg7[] = " **WELCOME** " , msg8[] = " * WARNING * ";
//======================================================
 void Move_Delay() {                  // Function used for text moving
  Delay_ms(500);                    // change text moving speed here
}
//===============
void code_enter()
{
kp = 0; // Reset key code variable
        // Wait for key to be pressed and released
do
  kp = Keypad_Key_Click(); // Store key code in kp variable
while (!kp);
        // Prepare value for output, transform key to it's ASCII value
switch (kp)
  {
    case 1: kp = 49; break; // 1
    case 2: kp = 50; break; // 2
    case 3: kp = 51; break; // 3
    case 5: kp = 52; break; // 4
    case 6: kp = 53; break; // 5
    case 7: kp = 54; break; // 6
    case 9: kp = 55; break; // 7
    case 10: kp = 56; break; // 8
    case 11: kp = 57; break; // 9
    case  4: kp = 65; break; // A
    case  8: kp = 66; break; // B
    case 12: kp = 67; break; // C
    case 16: kp = 68; break; // D
    case 13: kp = 42; break; // *
    case 14: kp = 48; break; // 0
    case 15: kp = 35; break; // #
  }
input_PW[i] = kp;
Lcd_Chr(2, i+6, input_PW[i]);  // Print key ASCII value on Lcd
i++;
}
//======================================
void delay_20ms()
{
Delay_ms(20);
}
//=========================================
void code_read()    //Read data from EEPROM
{
  user_PW[0] = EEPROM_Read(0x00);// Read data from address 0
  delay_20ms();
  user_PW[1] = EEPROM_Read(0x01);// Read data from address 1
  delay_20ms();
  user_PW[2] = EEPROM_Read(0x02);// Read data from address 2
  delay_20ms();
  user_PW[3] = EEPROM_Read(0x03);// Read data from address 3
  delay_20ms();
}
//===============================================
void code_write()    //Write data from EEPROM
{
  EEPROM_Write(0x00,input_PW[0]);// Write some data to address 0
  delay_20ms();
  EEPROM_Write(0x01,input_PW[1]);// Write some data to address 1
  delay_20ms();
  EEPROM_Write(0x02,input_PW[2]);// Write some data to address 2
  delay_20ms();
  EEPROM_Write(0x03,input_PW[3]);// Write some data to address 3
  delay_20ms();
}
//================================================
void change_code()
{ loop:
   Lcd_Cmd(_LCD_CLEAR);
   Lcd_Out(1,2, "NEW PASSWORD");
   Delay_ms(500);
   i=0;
   code_enter();//get input_PW[0]
   if(input_PW[0] == 42)//test input_PW[0] if * return to loop .
   {goto loop ;}
   code_enter();//get input_PW[1]
   if(input_PW[1] == 42)//test input_PW[1] if * return to loop .
   {goto loop ;}
   code_enter();
   if(input_PW[2] == 42)//test input_PW[2] if * return to loop .
   {goto loop ;}
   code_enter();
   if(input_PW[3] == 42)//test input_PW[3] if * return to loop .
   {goto loop ;}
   code_enter();
   if(input_PW[4] == 42)//test input_PW[4] if * return to loop .
   {goto loop ;}

   if(input_PW[4] == 35){ //if # then
      code_write();//write input_PW[] to EEPROM from address 0 to 3
      code_read();// read EEPROM from address 0 to 3 , save at user_PW[0] t0 user_PW[3]
      Delay_ms(500);
      Lcd_Out(2,5,msg6);//"**Done**"
      Delay_ms(2000);
      }
   else {
   Lcd_Cmd(_LCD_CLEAR);
   Lcd_Out(1,7, "ERROR");
   Delay_ms(1000); }
}
//======================================

void main()
{
  ADCON1 = 0x07;  // Configure AN pins as digital
  TRISA = 0x00;    // set direction to be output
  Keypad_Init();    // Initialize Keypad
  Lcd_Init();      // Initialize Lcd
  //=========================================================
  code_read();//Read EEPROM to user_PW[0] to user_PW[3]
  //===========
  //Initially all EEPROM locatins has 0xFF value
  if(user_PW[0] == 0xFF && user_PW[1] == 0xFF && user_PW[2] == 0xFF && user_PW[3] == 0xFF )
  {
  EEPROM_Write(0x00,'1');// Write some data at address 00
  delay_20ms();
  EEPROM_Write(0x01,'2');// Write some data at address 01
  delay_20ms();
  EEPROM_Write(0x02,'3');// Write some data at address 02
  delay_20ms();
  EEPROM_Write(0x03,'4');// Write some data at address 03
 }
 //=========================================================
 code_read();
 //===========
 Lcd_Cmd(_LCD_CLEAR);      // Clear display
 Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
 Delay_ms(500);
 Lcd_Out(1, 2,msg1 );//".. PROTECTED .."
 Delay_ms(2000);
 Lcd_Cmd(_LCD_CLEAR);      // Clear display
 //======================================
 cnt=0; // numbers of attempts
 //=====
 do
 { begin:
   PORTA.B0=1;//indication led on
   PORTA.B1=0; // lock off
   PORTA.B2=0; // alarm off
   Lcd_Cmd(_LCD_CLEAR);
   Lcd_Out(2, 4, " PRESS '*'");
   //========================
   i = 0;//before start of code enter
  code_enter();//press * to get input_PW[0]=42

  if(input_PW[0] == 42)// *
   {  start:
      Lcd_Cmd(_LCD_CLEAR);  // Clear display
      Lcd_Out(1, 2, msg2);//"ENTER PASSWORD"

       i = 0;//before start of code enter
      code_enter();//get input_PW[0] ,  if you press * you will begin from start
      if(input_PW[0] == 42)//*
         {goto start ;}

      code_enter();//get input_PW[1]
      if(input_PW[1] == 42)
         {goto start ;}

      code_enter();//get input_PW[2]
      if(input_PW[2] == 42)
         {goto start ;}

      code_enter();//get input_PW[3]
      if(input_PW[3] == 42)
         {goto start ;}

      code_enter();//get input_PW[4]
      if(input_PW[4] == 42)
         {goto start ;}
   //=====================================
    // If you want to change Master Key, add your numbers to '2' '3' '4' '5' '6'
      if(input_PW[0] == '2' && input_PW[1] == '3' && input_PW[2] == '4' && input_PW[3] == '5' && input_PW[4] == '6')          //check master code
      {
         code_enter();//get input_PW[5]
         if(input_PW[5] == 35)//#
         {
            change_code();
            goto begin ;
         }
      }
      //=======================================
      if(cnt<3 && input_PW[0] == user_PW[0] && input_PW[1] == user_PW[1] && input_PW[2] == user_PW
      [2] && input_PW[3] == user_PW[3] && input_PW[4] == 35) //compare code with store one
      {
         Lcd_Cmd(_LCD_CLEAR);  // Clear display
         Lcd_Out(1, 2, msg3);//"ACCESS GRANETED"
         Lcd_Out(2, 2, msg7);//" **WELCOME** "
         cnt=0;
         PORTA.B0=0;//indication led off
         PORTA.B1=1; //  open
         Delay_ms(3000);
         Lcd_Cmd(_LCD_CLEAR);
         Lcd_Out(2, 2, msg7);//" **WELCOME** "
                                          //Moving text
         for(i=0; i<4; i++) {              // Move text to the right 4 times
            Lcd_Cmd(_LCD_SHIFT_RIGHT);
            Move_Delay();}
         Delay_ms(500);
         for(i=0; i<8; i++) {              // Move text to the right 8 times
            Lcd_Cmd(_LCD_SHIFT_LEFT);
            Move_Delay();}
            Delay_ms(500);
         for(i=0; i<4; i++) {              // Move text to the right 4 times
            Lcd_Cmd(_LCD_SHIFT_RIGHT);
            Move_Delay();}
         Delay_ms(5000);    // Lock reactivate Time
         PORTA.B1=0;//close
         Lcd_Cmd(_LCD_CLEAR);
         Delay_ms(500);
         Lcd_Out(1,2,msg1);//".. PROTECTED .."
         Delay_ms(3000);
         Lcd_Cmd(_LCD_CLEAR);
      }

      else
      {
         cnt++;
         Lcd_Cmd(_LCD_CLEAR);
         Lcd_Out(1, 3,msg4 );//"ACCESS DENIED"
         Delay_ms(2000);
      }

      if(cnt>=3)
      {
         do
         {
            PORTA.B0=0;// led off
            PORTA.B2=1;//alarm on

            while(j<3) {      //repeat blink  3 times
               Lcd_Cmd(_LCD_CLEAR);
               Delay_ms(500);
               Lcd_Out(1, 3, msg8 );//" * WARNING * "
               Delay_ms(1000);
               Lcd_Cmd(_LCD_CLEAR);
               Delay_ms(500);
               Lcd_Out(1, 3, msg8 );//" * WARNING * "
               Delay_ms(1000);
               j++;
            }

            cnt=2;// one attempt only
            j=0;
            goto begin ;
         }
         while(1);
      }
   }
}
while(1);
}



Admin
Admin

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

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

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

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

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

الاتصالات التسلسلية Serial Communications
مقدمة :
تطبيقات الميكروكونترولر قد تتطلب فى بعض الحالات تنفيذ إقامة اتصالات تسلسلية مع غيره من أجهزة نقل البيانات مثل الذاكرات memories وأجهزة الاستشعار sensors والكومبيوتر وحتى ميكروكونترولر آخر .
بغرض إجراء الاتصالات التسلسلية ، بعض الميكروكونترولر يكون بها وحدات (تسمى موديولات modules ) مثل :
I2C, SPI, USART, USB . كل من هذه الأشكال من الاتصالات يسمح بالاتصال بالوحدات الأخرى . الاتصال من خلال I2C يعتبر نموذجيا للاتصال بالذاكرات التسلسلية مثل : 24LC64, 24LC128, 24LC512 وغيرها . يستخدم البروتوكول SPI للاتصال مع أجهزة التخزين الكبيرة مثل الذاكرة SD . الوحدة USART هى أكثر الوحدات إستخداما ، هذه الوحدة تسمح بالاتصال بالأجهزة مثل أجهزة الاستشعار ووحدات الإرسال والاستقبال Xbee والكومبيوتر الشخصى ووحدات GPS والمتحكمات الآخرى . وأخيرا وحدة USB ، والموجودة ضمن بناء قليل من المتحكمات مثل 18F2550 و 18F4550 ، تسمح بالاتصال مع الكومبيوتر الشخصى من خلال منفذ USB وتعرف باسم HID " جهاز واجة الانسان" Human Interface Device .

الوحدة (الموديول) USART :
الموديول USART هو وحدة اتصال تسلسلى غير متزامن ، هذه الميزة تجعل الطلب علية كبير حيث لا يحتاج لإشارة الساعة . ميزة أخرى ، أنه ثنائى الاتجاه بمعنى أنه يمكنه إرسال واستقبال المعلومات فى وقت واحد. لهذا الغرض فهو يستخدم خطين لنقل المعلومات ، أحدهما للإرسال والآخر للاستقبال . خواص بروتوكول هذا الاتصال هى:
"نبضة بدء" start bit وهى دائما بالمنطق المنخفض logic 0 و 8 أو 9 بت من البيانات data و واحد 1 أو1.5 أو 2 بتات إنتهاء stop bits . وأخيرا يجب تحديد سرعة النقل بنفس القيمة فى كل من الجهازين المتصلين وهى فى الحالة الافتراضية 9600 bps (ليست قاعدة) .
المخطط التالى يبين سلوك نقل البيانات باستخدام هذا البروتوكول :



يستخدم هذا البروتوكول بالكومبيوتر الشخصى وبالأجهزة الأخرى وهو معروف بالبروتوكول RS232 ، ويستخدم مستويات جهد محددة والتى تختلف عن مستويات الجهد التى يستخدمها الميكروكونترولر . فى البروتوكول RS232 يكون المنطق صفر بقيمة الجهد +12 volts ويكون المنطق واحد بقيمة الجهد-12 volts . الكومبيوتر الشخصى والأجهزة الأخرى التى تتعامل مع المنفذ RS232 ، تستخدم وصلة DB9 وبها 9 طرف معرفة كما فى الشكل التالى :



للاتصال الغير متزامن يجب إعداد التوصيلات كما فى الشكل التالى :



لعمل إتصال وربط الميكروكونترولر PIC مع جهاز به RS232 ، يستخدم المحول المعروف MAX232 . يجب أن يتم تنفيذ ذلك كما فى الشكل التالى :





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

الكود:
UART1_Init (const unsigned long baud_rate);

تستخدم هذه الدالة لتهيئة (إعداد) الموديول USART وتحديد سرعة الاتصال عن طريق البارامتر baud_rate .
مثال :
الكود:
// Initialize hardware UART1 and establish communication at 9600 bps
UART1_Init(9600);
 


الدالة :

الكود:
char UART1_Data_Ready();

تستخدم هذه الدالة فى اختبار ما إذا كان هناك بيانات بحافز buffer الاستقبال جاهزة للقراءة فتعود بواحد (1) وإلا فإن لم توجد بيانات فى حافز الاستقبال عادت بالصفر (0) .
مثال :

الكود:
// If data is ready, read it:
if (UART1_Data_Ready() == 1) {
 receive = UART1_Read();
 }

الدالة :

الكود:
 char UART1_Tx_Idle();

تستخدم هذه الدالة فى اختبار ما إذا كان مسجل الإزاحة للإرسال فارغ (أى تم إرسال البيانات) فتعود بواحد أما إذا كان هناك بيانات فى مسجل الإزاحة للإرسال والموديول جاهز لإرسال بيانات جديدة فتعود بالصفر .
مثال :

الكود:
// If the previous data has been shifted out, send next data:
if (UART1_Tx_Idle() == 1) {
  UART1_Write(_data);
 }

الدالة :

الكود:
 char UART1_Read();

تستخدم هذه الدالة فى استقبال (قراءة) بايت من حافز الدخل وتعود بقيمته.

الكود:
// If data is ready, read it:
if (UART1_Data_Ready() == 1) {
 receive = UART1_Read();
 }


الدالة :

الكود:
UART1_Read_Text (char * Output, char *Delimiter, char Attempts);

تستخدم هذه الدالة فى قراءة سلسلة (تتابع) الحروف المخزنة بالمتغير المشار إلية بالبارامتر Output حتى يتم كشف تسلسل بشكل محدد delimiter sequence مبين بالبارامتر Delimiter . البارامتر Attempts يحدد عدد الحروف المتوقعة (طول النص) بالتسلسل المحدد . هذه الدالة تستدعى كوحدة واحدة حيث يتم تنفيذها عند وجود تتابع سلسلة الحروف بالشكل المحدد فإذا لم يوجد التتابع بالشكل المحدد يتم الخروج من الإجراء الموجود به الدالة .
مثال :

الكود:

UART1_Init(4800);                        // initialize UART1 module
Delay_ms(100);
while (1) {
  if (UART1_Data_Ready() == 1) {          // if data is received
    UART1_Read_Text(output, "OK", 10);    // reads text until 'OK' is found
    UART1_Write_Text(output);            // sends back text
 }
}

الدالة :

الكود:
UART1_Write(char _data);

تستخدم هذه الدالة فى إرسال بايت البيانات الموجود بالمتغير _data من خلال موديول UART .
مثال :

الكود:
unsigned char _data = 0x1E;
...
UART1_Write(_data);

الدالة :

الكود:
UART1_Write_Text(char * UART_text);

تستخدم هذه الدالة فى إرسال نص خلال UART ويجب أن ينتهى النص بالصفر 0 . هذا النص معطى بالبارامتر UART_text .
مثال :

الكود:
UART1_Init(4800);                        // initialize UART1 module
Delay_ms(100);
while (1) {
  if (UART1_Data_Ready() == 1) {          // if data is received
    UART1_Read_Text(output, "OK", 10);    // reads text until 'OK' is found
    UART1_Write_Text(output);            // sends back text
 }
}


Admin
Admin

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

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

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

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

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

تدريب تمهيدى 1 : تدريب مكتبة UART
هذا التدريب يستعرض تبادل بيانات بسيط من خلال وحدة UART . عندما يستقبل الميكروكونترولر بيانات ، يقوم على الفور بإرسالها عائدة .

الكود:
char uart_rd;

void main() {
  UART1_Init(9600);              // Initialize UART module at 9600 bps
  Delay_ms(100);                  // Wait for UART module to stabilize
 
  UART1_Write_Text("Start");
  UART1_Write(10);
  UART1_Write(13);
 
  while (1) {                    // Endless loop
    if (UART1_Data_Ready()) {    // If data is received,
      uart_rd = UART1_Read();    // read the received data,
      UART1_Write(uart_rd);      // and send data via UART
    }
  }
}
 




تدريب تمهيدى 2 :
لتنفيذ هذا التدريب ببرنامج ISIS يتم جلب العناصر التالية PIC 16F877A و VIRTUAL TERMINAL وتكوين الدائرة كما فى الشكل التالى :




الوحدة الطرفية التخيلية VIRTUAL TERMINAL هى جهاز لمحاكاة الاتصال التسلسلى ولها نفس سلوك إداة النوافذ Windows HyperTerminal . هذا الجهاز يسمح بتحرير خواص الاتصالات مثل : عدد بتات البيانات ، وسرعة النقل ، وعدد بتات النهاية وغيرها . مع ذلك ، فإن الجهاز معد بسرعة إفتراضية 9600 bps وجاهز للاستخدام مع موديول UART .
للتحقق من عمل هذا الموديول يمكن ترجمة ومحاكاة البرنامج التالى :

الكود:
 void main (void)
 {
    // Declaration of variables.
    char Data;
    UART1_Init (9600);    //  initialize UART1 module
   Delay_ms(100);
    // Transmitting the text: Welcome.
    UART1_Write_Text ("Welcome to the simulator:");
    UART1_Write (13);    // It transmits the ASCII  CR = Crriage return
    UART1_Write (10);    // It transmits the ASCII NL=New line
    // Text is transmitted with key.
    UART1_Write_Text ("Press a key! ...");
    UART1_Write (13);    // It transmits the ASCII  CR = Crriage return
    UART1_Write (10);    // It transmits the ASCII NL=New line
    while (1) // infinite loop.
    {
       // The if statement tests whether a data is ready to read.
       if (UART1_Data_Ready () == 1)
       {
        // It reads the data from the buffer.
        Data = UART1_Read ();
        // Print text feedback.
        UART1_Write_Text ("you pressed the key:");
        UART1_Write (Data);    // received data is transmitted.
        UART1_Write (13);    // It transmits the ASCII  CR = Crriage return
        UART1_Write (10);       // It transmits the ASCII NL=New line
       }
    }
 }

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





Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الخميس يوليو 06, 2017 8:07 pm

الاتصال التسلسلى بين الدوائر المتكاملة   I2C Inter-Integrated Circuit
المرجع :
http://embedded-lab.com/blog/?p=2583

مقدمة :
نظام I2C هو واجة ربط متسلسلة لمسافة قصيرة والتى تتطلب ناقل ذو خطين فقط لنقل البيانات . ولقد أخترعت من قبل شركة فيليبس عام 1980 ، وذلك لتوفير اتصالات سهلة على اللوحة المطبوعة بين وحدة المعالجة المركزية CPU ورقائق الطرفيات المختلفة فى جهاز التليفزيون . اليوم يتم استخدامها على نطاق واسع فى أنواع متعددة من الأنظمة المدمجة لربط الأجهزة الطرفية ذات السرعة المنخفضة ( الذاكرات EEPROMs الخارجية وأجهزة الاستشعار الرقمية ومشغلات وحدات العرض LCD ..ألخ ) بالمتحكم الرئيسى .
سوف نتناول لمحة عامة عن بروتوكول I2C وتنفيذه فى الميكروكونترولر PIC وطريقة توصيل جهاز مفرد أو عدد من الأجهزة بناقل I2C مشترك . سوف نوضح هذه التقنية بتوصيل 2 دائرة متكاملة EEPROM نوع (24LC512) وجهاز الاستشعار بالحرارة (DS1631) مع الميكروكونترولر PIC18F2550 .

مبدأ العمل :
نظام الناقل I2C له خطين : خط البيانات التسلسلية SDA وخط الساعة التسلسلية SCL . أى بيانات ترسل من أحد الأجهزة إلى الجهاز الآخر تمر خلال خط البيانات التسلسلية SDA ، فى حين أن خط الساعة التسلسلية يوفر ساعة التزامن اللازمة لنقل البيانات .
الأجزة الموجودة على الناقل I2C إما أن تكون "سيد" Masters (ماستر) أو "تابع" Slaves . فقط الجهاز الماستر هو الذى يمكنه بدء نقل البيانات بينما التابع يستجيب للماستر . من الممكن أن يكون لدينا أجهزة ماستر متعددة على نفس الناقل المشترك ، ولكن جهاز ماستر واحد فقط يمكن أن يكون فعال فى زمن معين . خط الساعة SCL دائما يتم قيادته عن طريق الماستر . سوف نتناول حالة جهاز ماستر واحد وهو الميكروكونترولرPIC18F2550 .
الشكل التالى يبين ناقل I2C بماستر منفرد وثلاثة توابع . التوابع لا يمكنها أبدا بدء نقل البيانات ولكن يمكنها نقل البيانات عبر الناقل I2C ودائما يكون ذلك تحت سيطرة الماستر .



كل من الخط SCL والخط SDA ذات دوائر قيادة بمصب مفتوح open drain drivers ، وبالتالى يتم توصيلها بالجهد الموجب للمصدر من خلال مقاومات سحب لأعلى pull-up resistors . وهذا يعنى أن أجهزة I2C يمكنها فقط سحب الخط لأسفل ولكن لا يمكنها جعله مرتفعا . عندما لا يقوم أى جهاز بسحب الخط فسوف يكون هذا الخط طافيا لأعلى float high من خلال مقاومة السحب لأعلى . وهذا هو السبب فى أهمية مقاومات السحب فى نظام I2C .
يمكن نقل البيانات بالناقل I2C بمعدل حتى  100 Kbps ( فى النظام القياسى standard) أو بمعدل  400 Kbps ( فى النظام السريع fast) أو حتى  3.4 Mbps ( فى نظام السرعة المرتفعة high-speed) .

أحوال البدء والإيقاف Start and Stop conditions
قبل القيام بأى تعامل على الناقل ، يتم إصدار حالة "البدء" Start  عن طريق الجهاز الماستر لإبلاغ جميع الأجهزة التابعة أن شيئا ما على وشك أن ينتقل على الناقل . ونتيجة لذلك ، فإن جميع الأجهزة التابعة الموصلة تكون فى حالة إستماع لخط البيانات التسلسلية إنتظارا للتعليمات ( بمعنى أن الناقل مشغول) .
يتم إصدار حالة البدء عن طريق سحب خط البيانات التسلسلية SDA إلى الحالة المنخفضة يليه خط الساعة التسلسلية SCL .
بمجرد الانتهاء من نقل البيانات يقوم الجهاز الماستر للناقل بإرسال حالة  " الإيقاف" (الانتهاء) Stop لإبلاغ الأجهزة الأخرى بالرغبة فى الإفراج (تحرير) عن الناقل (بمعنى أن الناقل غير مشغول) . الإشارات المستخدمة فى حالة الإيقاف هى تحرير خط الساعة SCL يليه تحرير خط البيانات SDA .
تذكر أنه عندما يتم تحرير الخطوط ، فإنها تكون طافية لأعلى بسبب مقاومات السحب لأعلى . وهكذا فإن تتابع البدء والإنتهاء يعتبر بمثابة إشارة أو علامة لبداية ونهاية التعامل مع الجهاز التابع .



عنونة أجهزة الناقل I2CI2C device addressing :
كل جهاز متصل بالناقل I2C يكون قابل للعنونة برمجيا عن طريق عنوان منفرد ذو 7 بت 7-bit أو 10 بت 10-bit . استخدام العنوان ذو 10 بت غير شائع وبالتالى لن يتم تناوله هنا.
البايت الأول الذى يرسل بعد حالة البدء يعرف ببايت التحكم Control byte . السبعة بتات الأولى لبايت التحكم تشكل عناوين الأجهزة التابعة ، فى حين أن البت الثامن (LSB) هو بت اتجاه البيانات (R/W) :
• عندما يكون هذا البت بصفر (0) فهذا يشير على أن الجهاز الماستر سوف "يكتب" (يرسل) معلومات إلى الجهاز التابع المختار ( بالسبعة بتات الأولى) .
• وعندما يكون هذا البت بواحد (1) فهذا يشير على أن جهاز الماستر سوف "يقرأ" (يستقبل) البيانات من الجهاز التابع المختار ( بالسبعة بتات الأولى) .
فى أجهزة السبعة بت ،  عادة تكون الأربعة بتات الأولى ثابتة fixed لنفس الجهاز ،  ويتم تعيين الثلاثة بتات التالية عن طريق أطراف عناوين الأجهزة hardware (A0, A1, A2) وهذا يسمح للمستخدم بتعديل عناوين ناقل I2C بما يصل حتى ثمانية من نفس الأجهزة بالعمل على الناقل I2C . هذه الأطراف يتم حفظها فى الحالة المرتفعة عن طريق VCC أو الحالة المنخفضة عن طريق الأرضى GND . سوف يتم ماقشة ذلك فى الدائرة الكهربية وكيفية تحديد عنوان الجهاز على الناقل .




عندما يتم إرسال بايت التحكم ، فإن كل جهاز بالنظام يقارن السبعة بتات الأولى المستقبلة مع عنوانه . إذا تطابقا ، فإن الجهاز يعتبر نفسه المخاطب بواسطة (تحت أمر) الجهاز الماستر ليكون إما " مستقبل – تابع "
slave-receiver أو " مرسل- تابع " slave-transmitter وهذا يتوقف على قيمة بت اتجاه البيانات (البت الثامنة) .

نقل البيانات Data transfer :
كل بايت يوضع على خط البيانات SDA يجب أن يكون بطول 8 بتات 8-bits . ترسل البيانات على خط البيانات SDA بدءا بالبت الأكثر أهمية(MSB) أولا وينتج خط الساعة SCL ساعة التزامن . تعتبر البيانات على الخط SDA صالحة (صحيحة) عندما يكون الخط SCL فى الحالة المرتفعة ، وبالتالى يجب أن تستقر البيانات خلال فترة الحالة المرتفعة للساعة . الحالة المرتفعة أو المنخفضة لحالة خط البيانات يجب أن تتغير عندما تكون الإشارة على الخط  SCL فى الحالة المنخفضة . الشكل التالى يبين توقيت عمل كل بت :



إذا كان الجهاز التابع ليس فى وضع يمكنه من استقبال أو إرسال بايت كامل من البيانات حتى يؤدى مهمة أخرى ، على سبيل المثال خدمة مقاطعة داخلية ، فإنه يمكنه الحفاظ على الخط SCL منخفضا لإجبار الجهاز الماستر على حالة الانتظار . يستمر نقل البيانات عندما يكون الجهاز التابع جاهزا لبايت آخر من البيانات ويحرر خط الساعة .
دائما يتم إنهاء عملية نقل البيانات بحالة الإنهاء Stop التى تتولد عن طريق الجهاز الماستر . ومع ذلك ، إذا رغب الجهاز الماستر فى البقاء بالاتصال بالناقل ، فيمكنه توليد حالة "تكرار- البدء" repeated-Start وعنونة جهاز تابع آخر دون أن يولد حالة الإيقاف أولا .
التسلم (الإشعار بالاستلام أو المعرفة) Acknowledgment :
عادة يتم إلزام المستقبل الذى تمت عنونته بتوليد إشارة "إستلام" acknowledge (ACK)  بعد كل بايت يتم استقباله . تحدث إشارة الاستلام بعد نقل البت الثامنة لأى تعامل . خلال تلك الحالة يجب على المرسل تحرير الخط SDA للسماح للمستقبل بقيادته . يقوم المستقبل بقيادة إشارة SDA للحالة المنخفضة للدلالة على استلام البايت . إذا لم يقم المستقبل بقيادة الخط SDA للحالة المنخفضة ، فإن الحالة تكون حالة عدم إستلام no-acknowledge (NACK) ويتم إلغاء (إجهاض) العملية . إذا كان البايت المرسل هو بايت التحكم (slave address + R/W bit) ، عند ذلك فقط الجهاز التابع الذى له عنوان متطابق سوف يستجيب بإشارة الاستلام .

الآن دعنا نناقش كيف يمكن لهذه العملية ، بمختلف تسلسلها فى العمل ، أن تحدث أثناء اتصال الميكروكونترولر PIC18F2550 مع الذاكرة 24LC512 EEPROM  و مستشعر درجة الحرارة DS1631 من خلال الناقل I2C .
الوحدة أو الموديول MSSP (Master Synchronous Serial Port) بالميكروكونترولر PIC18F2550 يسمح بالاتصالI2C خلال طرفى الدخل / الخرج RB0/SDA (21) و RB1/SCL (22) .
لن يتم هنا مناقشة تفاصيل عمل هذه الوحدة بسبب استخدم المترجم ميكروسى الذى يوفر دوال روتينات لمكتبة الاتصال I2C .

الدائرة المتكاملة (24LC512) ذاكرة EEPROM تسلسلية:
الدائرة المتكاملة 24LC512 هى ذاكرة EEPROM تسلسلية من شركة ميكروشيب بسعة 64K x 8 (512 Kbits) ، متوافقة مع الاتصال I2C . مخطط الأطراف مبين بالشكل أدناه  .



الأربعة بتات الأولى ، الثابتة ، من السبعة بتات الخاصة بالعنوان لهذه الشريحة يتم تحديدها بالشكل ’1010′ أى A . الثلاثة بتات التالية قابلة للبرمجة من خلال أطرافها A0, A1, A2 . على سبيل المثال ، للجهاز 24LC512 عندما يكون A0 بالمنطق المرتفع ومع توصيل الأطراف A1،A2 بالأرضى فسوف يكون لدينا عنوان من السبعة بتات التالية ’1010001′ . وهذا التخطيط يسمح بعنونة ثمانى أجهزة متشابهة كحد أقصى على نفس الناقل I2C .

عملية كتابة البايت Byte Write operation :
لعملية كتابة بايت يتطلب 2 بايت من العناوين لاختيار واحد من أصل 65536 موقع فى ذاكرة EEPROM . الجهاز الماستر يوفرهما ، بعد إرسال بايت التحكم . الشريحة 24LC512  تستجيب بنبضة التسلم (كتوقيع بالاستلام ) acknowledge بعد استقبال كل بايت للعنوان . بعد ذلك يرسل الماستر بايت البيانات المطلوب كتابته بالذاكرة . عند استلام (استقبال) هذه البيانات ترسل الشريحة 24LC512  نبضة التسلم . عندئذ يقوم الماستر بإنهاء نقل البيانات عن طريق إصدار حالة الإيقاف .



عملية كتابة صفحة Page Write operation :
لتقليل زمن دورة الكتابة ، تقدم الشريحة 24LC512 ميزة كتابة صفحة ، والتى تسمح بالكتابة فى وقت واحد حتى 128 بايت متجاورة . يتم بدء كتابة الصفحة بنقس طريقة كتابة البايت ، ولكن بدلا من توليد حالة الإيقاف ، يقوم الماستر بإرسال حتى 127 بايت إضافى ، والتى تخزن مؤقتا فى المخزن المؤقت للصفحة بالشريحة on-chip page buffer وسوف يتم كتابتها بالذاكرة بعد أن يرسل الماستر حالة الإيقاف .



عملية القراءة Read operation :
بدء عملية القراءة تتم بنفس الطريقة مثل عملية الكتابة باستثناء أنه يتم تعيين البت R/W ،اى بايت التحكم فى القراءة / الكتابة ، بواحد ‘1’ . الشريحة 24LC512 تسمح بثلاثة أنواع أساسية من عمليات القراءة : قراءة العنوان الحالى ، والقراءة العشوائية والقراءة المتسلسلة (المتتابعة) .
داخليا ، تحتوى شريحة EEPROM على عداد عنوان والذى يحفظ عنوان آخر كلمة وصلت ، ويتزايد بواحد . ولذلك ، إذا كانت القراءة التى وصلت سابقا previous كانت للعنوان ‘n’ فإن العنوان الحالى لعملية القراءة يجب أن يصل للبيانات من العنوان n + 1 . عند استلام بايت التحكم مع تحديد البت R/W بواحد (1)  فإن EEPROM تصدر إشارة التسلم وترسل بايت البيانات للعنوان الحالى . الماستر سوف لا يتسلم عملية النقل لكن يولد حالة الإيقاف التالية ويقطع EEPROM الإرسال .




عمليات القراءة العشوائية تسمح للماستر بالوصول لأى موقع ذاكرة بطريقة عشوائية . لتنفيذ هذا النوع من عمليات القراءة ، لابد أولا من تحديد عنوان الكلمة . يتم ذلك عن طريق إرسال عنوان الكلمة للشريحة 24LC512  كجزء من عملية الكتابة ( تحديد البت R/W بصفر ) . بعد إرسال عنوان الكلمة ، يولد الماستر حالة "تكرار البدء" بعد التسلم . وهذا ينهى عملية الكتابة . عندئذ يصدر الماستر بايت التحكم مرة أخرى ولكن مع تحديد البت R/W بواحد . عندئذ سوف تقوم EEPROM بإصدار التسلم وترسل بيانات8-bit للكلمة . الماستر سوف لا يتسلم النقل ولكن يولد حالة الإيقاف والتى تتسبب فى أن ينهى EEPROM الإرسال .



يتم بدء القراءة التتابعية عن طريق إما العنوان الحالى أو قراءة العنوان عشوائيا . بعد استقبال البايت الأول من 24LC512 ، يصدر الماستر التسلم بدلا من حالة الإيقاف المستخدمة فى العنوان الحالى أو القراءة العشوائية . هذا التسلم يوجه 24LC512 لإرسال الكلمة 8 بت التالية بالعنوان التتابعى . بعد إرسال آخر بايت إلى الماستر ، فإن الماستر سوف لا يولد تسلم ، لكن يولد حالة إيقاف .




حماية الكتابة Write Protect WP :
الطرف رقم 7 بالشريحة 24LC512 هو مدخل حماية الكتابة بالأجهزة hardware  . إذا تم ربط هذا الطرف بالجهد الموجب Vcc ، فإن ذلك يحول دون عمليات الكتابة ولكن عمليات القراءة لا تتأثر . هنا سوف نوصل هذا الطرف بالأرضى .

الناقل I2C لمستشعر درجة الحرارة (DS1631) :
الشريحة DS1631 هى مقياس رقمى لدرجة الحرارة ، مصنع بمعرفة شركة Dallas  ، والذى يوفر حساسية قياس بدقة
9, 10, 11, 12-bit ( حسب اختيار المستخدم) ، لقياس درجة الحرارة فى المدى -55 °C to 125 °C  . الدقة الافتراضية عند توصيل القدرة هى 12-bit ،  والمقابلة لتزايد فى درجة الحرارة قدره 0.0625  °C (الحساسية). يتحقق الاتصال مع DS1631 من خلال واجهة الناقل I2C وثلاثة أطراف للعنونة (A0, A1, A2) بما يسمح لثمانى أجهزة من نفس النوع بالاتصال بنفس الخطين للناقل . العنوان ذات السبع بتات لكل جهاز تابع هى 1 0 0 1 A2 A1 A0 حيث A0, A1, A2  هى اختيارات المستخدم من خلال أطراف الدخل المناظرة .

قياس درجة الحرارة Temperature measurement :
يوصى بقراءة الداتا شيت الخاصة بالشريحة DS1631 للاطلاع على تفاصيل بناؤها وعملية تحويل درجة الحرارة .
هنا ، سوف نتناول فقط نظام الطلقة (الدفعة) الواحدة one-shot mode لتحويل درجة الحرارة . لنفترض ، أن الجهاز تم توصيله بالقدرة للتو ، وأن دقة التحويل محددة بقيمة 12-bit . فى نظام الطلقة الواحدة يبدأ المستشعر DS1631 بتحويل درحة الحرارة إلى كلمة رقمية مكونة من 12-bit بعد استقبال بايت الأمر 51h من الماستر .وهو ما يعرف بأمر بدء تحويل درجة الحرارة Start Convert T . بعد التحويل ، يتم تخزين درجة الحرارة الرقمية كعدد 16-bit فى شكل
two’s complement  ، فى سجلى درجة الحرارة المكونة من 2 بايت : TH و TL كما فى الشكل أدناه . بت الإشارة Sign bit (S) تشير إلى ما إذا كانت درجة الحرارة موجبة (S=0) أو سالبة (S=1) .





يمكن للماستر قراءة بيانات درجة الحرارة من DS1631 عن طريق إرسال أمر قراءة درجة الحرارة
Read Temperature (AAh) . بعد استقبال التسلم ACK استجابة للأمر ، يجب أن يولد الماستر حالة تكرار البدء repeated Start يليها بايت التحكم بعنوان نفس التابع كما فى بايت التحكم الأول . مع ذلك ، هذه المرة البت R/W يجب أن تكون بواحد (1) ، والتى تخبر DS1631 بأنه يتم إجراء "قراءة" . يرسل DS1631 التسلم ACK كاستجابة لبايت التحكم هذا ، ويبدأ فى إرسال البيانات المطلوبة فى دورة الساعة التالية . لقراءة 2 بايت (TH and TL registers) ، يجب أن يستجيب الماستر لبيانات أول بايت بالتسلم ACK ولبيانات ثانى بايت بعدم التسلم NACK متبوعة بحالة إيقاف . إذا كان هناك حاجة فقط لبيانات البايت الأكثر أهمية ، عندئذ يمكن للماستر أن يصدر عدم التسلم NACK متبوعة بحالة إيقاف بعد قراءة بيانات أول بايت .



Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الجمعة يوليو 07, 2017 11:35 am

المترجم ميكروسى برو والاتصال التسلسلى I2C :
المترجم mikroC Pro for PIC يقدم مكتبة دوال (روتينات) للتعامل مع الاتصال بالناقل I2C ، فيما يلى ملخص لها :
الدالة :

الكود:
void I2C1_Init(const unsigned long clock);

أول شىء يتعين علينا القيام به هو تهيئة ( إعداد ) الوحدة (الموديول) MSSP للاتصال I2C . يمكن أن يتم ذلك بالدالة I2C1_Init ، على سبيل المثال الدالة :

الكود:
 I2C_Init(100000)

سوف تهىء الموديول MSSP من أجل الاتصال I2C بتردد (سرعة) KHz100 .

الدالة :

الكود:
unsigned short I2C1_Start(void);

هذه الدالة تحدد ما إذا كان الناقل IC حرا free فيتم إصدار إشارة حالة "البدء" Start .
عائد (نتيجة) هذه الدالة بالصفر إذا لم يكن هناك خطأ .
مثال :

الكود:
 I2C1_Start();

الدالة :

الكود:
void I2C1_Repeated_Start(void);

لإصدار حالة "تكرار البدء" repeated-start .
مثال :

الكود:
I2C1_Repeated_Start();

الدالة :

الكود:
 unsigned short I2C1_Is_Idle(void);

تتحقق مما إذا كان الناقل I2Cحرا . إذا كان حرا تعود بواحد وإن لم يكن حرا (مشغول) تعود بالصفر .
مثال :

الكود:
if (I2C1_Is_Idle()) {...}

الدالة :

الكود:
unsigned short I2C1_Rd(unsigned short ack);

لقراءة بايت واحد من التابع وإرسال إشارة "عدم التسلم" NACK إذا كان البارامتر ack بصفر (0) وإلا ترسل "التسلم" acknowledge .
مثال :

الكود:
 //Read data and send not acknowledge signal:
unsigned short take;
...
take = I2C1_Rd(0);

على سبيل المثال ، إذا احتاج الميكروكونترولر لقراءة درجة حرارة فى شكل 2 بايت من DS1631 فيجب عليه استخدام I2C1_Rd(1) لقراءة البايت الأول (مع إشارة استلام) و I2C1_Rd(0) لقراءة البايت الثانى (بدون إشارة إستلام) .

الدالة :

الكود:
unsigned short I2C1_Wr(unsigned short data_);

لإرسال بيانات بايت data_ من خلال الناقل I2C . هذه الدالة تعود بالصفر إذا لم يكن هناك خطأ .
مثال :

الكود:
I2C1_Wr(0xA3);

الدالة :

الكود:
void I2C1_Stop(void);

لإصدار حالة الإيقاف Stop .
مثال :

الكود:
I2C1_Stop();

مثال مكتبة الميكروسى :
هذا الكود يستعرض استخدام مكتبة I2C . يتم توصيل الأطراف SCL و SDA للميكروكونترولر بالأطراف المناظرة بذاكرة EEPROM .
يقوم البرنامج بإرسال بيانات إلى EEPROM (يتم كتابة البيانات 0xAA على العنوان 2 ) . بعد ذلك ، يتم قراءة البيانات من خلال الناقل I2C من EEPROM وإرسال قيمتها إلى المنفذ PORTB .

الكود:
 void main(){
  PORTB = 0;
  TRISB = 0;                // Configure PORTB as output

  I2C1_Init(100000);        // initialize I2C communication
//==== Writing operation =========
  I2C1_Start();              // issue I2C start signal
  I2C1_Wr(0xA2);        // send byte via I2C  (device address + W), (1010-001-0)
  I2C1_Wr(2);                // send byte (address of EEPROM location)
  I2C1_Wr(0xAA);            // send data (data to be written)
  I2C1_Stop();              // issue I2C stop signal

  Delay_100ms();

//===== Reading operation ========
  I2C1_Start();              // issue I2C start signal
  I2C1_Wr(0xA2);            // send byte via I2C  (device address + W)
  I2C1_Wr(2);                // send byte (data address)
  I2C1_Repeated_Start();    // issue I2C signal repeated start
  I2C1_Wr(0xA3);            // send byte (device address + R),(1010-001-1)
  PORTB = I2C1_Rd(0u);      // Read the data (NO acknowledge)
  I2C1_Stop();              // issue I2C stop signal
}




تدريب :
فى هذا التدريب سوف نستخدم شريحة الذاكرة 24C64 EEPROM كجهاز تابع ، وسوف نستعرض عملية الكتابة إلى والقراءة من جهاز يمتلك وحدة I2C مع بيان الخرج على ليدات . فى برنامج Proteus سوف نحتاج إلى جهاز I2C Debugger والذى يتم توصيله على التوازى مع كل من الميكروكونترولر PIC16F877A والذاكرة عبر خط الساعة SCL وخط البيانات SDA كما هو مبين بالدائرة الكهربية .
فى هذا التدريب سوف نكتب 00000001 إلى أول موقع ذاكرة ، ونكتب 00000010 إلى ثانى موقع ذاكرة ونكتب 00000100 إلى ثالث موفع ذاكرة وهكذا على التتابع حتى الموقع الثامن 10000000 ، بعد ذلك يتم القراءة المتتابعة وعرض النتيجة على ليدات متصلة بالمنفذ PORTB .
الدائرة الكهربية :



البرنامج :

الكود:
void write_EEPROM(unsigned int address, unsigned int dat)
{

unsigned int temp;
  I2C1_Start();            // issue I2C start signal
  I2C1_Wr(0xA0);          // send byte via I2C (device address + W)
temp = address >> 8;    //saving higher order address to temp
  I2C1_Wr(temp);          //sending higher order address
  I2C1_Wr(address);        //sending lower order address
  I2C1_Wr(dat);            // send data (data to be written)
  I2C1_Stop();            // issue I2C stop signal
Delay_ms(20);
}

unsigned int read_EEPROM(unsigned int address)
{
unsigned int temp;
  I2C1_Start();            // issue I2C start signal
  I2C1_Wr(0xA0);          // send byte via I2C (device address + W)
temp = address >> 8;    //saving higher order address to temp
  I2C1_Wr(temp);          //sending higher order address
  I2C1_Wr(address);        //sending lower order address
  I2C1_Repeated_Start();  // issue I2C signal repeated start
  I2C1_Wr(0xA1);          // send byte (device address + R)
temp = I2C1_Rd(0u);      // Read the data (NO acknowledge)
  I2C1_Stop();
return temp;
}

void main()
{
unsigned int a, i;
TRISB  = 0;            // To make it output port
  PORTB = 0;              // To make it output port
  CMCON = 0x07;          // To turn off comparators
  ADCON1 = 0x06;          // To turn off analog to digital converters
  I2C1_Init(100000);
do
  {
for(i=0,a=1;i<8;i++)
      {
write_EEPROM(i, a);
Delay_ms(30);
        a = a<<1;
      }

for(i=0;i<8;i++)
      {
        PORTB = read_EEPROM(i);
Delay_ms(100);
      }
}while(1);

}
 




Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الجمعة يوليو 07, 2017 11:44 am

تدريب : توصيل أجهزة متعددة على متن ناقل I2C مشترك :
الدائرة الكهربية :




يوجد 2 ذاكرة EEPROM تسلسلية نوع 24LC512 و مستشعر لدرجة الحرارة DS1631 متصلة على ناقل I2C مشترك . يتم تجنب الصراع conflict بين شريحتى الذاكرة EEPROMs بتوصيل الطرف A0 لأحدهما بالأرضى والطرف A0 للثانى بالجهد Vcc . العناوين ذات السبع بتات للثلاثة أجهزة مبينة بالشكل . المقاومتين 10K هى مقاومات السحب لأعلى لخطى الناقل I2C . خط البيانات SDA وخط الساعة SCL متصلان بالأطراف RB0 و RB1 للميكروكونترولر PIC18F2550 على الترتيب .
كما يتم توصيل وحدة عرض LCD لعرض عمليات القراءة والكتابة على الناقل I2C .

البرنامج :
سوف نكتب برنامج لاختبار الاتصال بالناقل I2C بين الميكروكونترولر PIC18F2550 والثلاثة أجهزة المتصلة بالناقل المشترك . سوف يقوم البرنامح أولا بالتحقق (اختبار) من وجود جميع الأجهزة الثلاثة على الناقل ، ثم يرسل أمر تحويل درجة الحرارة إلى الجهاز DS1631 . عندئذ يتم قراءة درجة الحرارة فى شكل 2 بايت وتخزينها فى شريحتى الذاكرة
( البايت المرتفع فى شريحة EEPROM الأولى والبايت المنخفض فى شريحة EEPROM الثانية ، بدءا من الموقع صفر ). بعد تسجيل خمس عينات ، يتم قراءتها بشكل تسلسلى من مواقع ذاكرة EEPROM ، وتحويلها إلى وحدات درجة حرارة فعلية (°C) وعرضها على شاشة وحدة العرض LCD .
فى برنامجنا ، سوف يقوم PIC18F2550 أولا بالتحقق من تواجد (إتاحة) الثلاثة أجهزة على الناقل . يتم ذلك بإرسال عنوان الجهاز لكل منهم فإذا تسلمه ، فهذا يعنى أنه موجود . دالة (روتين) الميكروسى للتحقق من وجود الجهاز على الناقل I2C كما يلى :

الكود:
void check_device(unsigned short dev_address){
 I2C1_Start();
 if (I2C1_Wr(dev_address)){ //I2C1_Wr Returns 0 if there were no errors.

  Lcd_Out(2,1,"Device not found");
 }
 else Lcd_Out(2,1,"Device is OK");
 I2C1_Stop();
}

جزء البرنامج التالى يسمح للميكروكونترولر PIC18F2550 بإرسال أمر "بدء تحويل درجة الحرارة"
Start Convert T إلى DS1631 ، ثم الانتظار لمدة 750 ms حتى يتم إجراء تحويل درجة الحرارة فى شكل 12-bit ، وفى النهاية يتم استقبال قراءة درجة الحرارة المكونة من 2 بايت .

الكود:
 // Read temperature
 I2C1_Start();
 I2C1_Wr(DS1631);              // Send device address
 I2C1_Wr(0x51);                // Start Convert Temp command
 I2C1_Stop();
 Delay_ms(750);

 I2C1_Start();
 I2C1_Wr(DS1631);              // DS1631 Address again , with write
 I2C1_Wr(0xAA);                // Read Temperature command
 I2C1_Repeated_Start();
 I2C1_Wr(DS1631+1);              // Address with Read
 MS_Byte = I2C1_Rd(1);          // Read MSB and send ACK
 LS_Byte = I2C1_Rd(0);            // Read LSB and send NAK
 I2C1_Stop();

يمكنك ملاحظة أنه عند قراءة البايت الأخير فإن PIC18F2550 ليس بحاجة لإرسال نبضة "تسلم" acknowledge.

الروتينات التالية سوف تؤدى عمليات قراءة وكتابة بايت مع شرائح الذاكرة EEPROMs .

الكود:
//--------------- Reads data from 24LC512 EEPROM - single location
unsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {
 unsigned short rAddrH, rAddrL, result;
 rAddrH = 0;
 rAddrL = rAddress;
 I2C1_Start();            // issue I2C1 start signal
 I2C1_Wr(EEPROM_Select);    // send byte via I2C1  (device address + W)
 I2C1_Wr(rAddrH);          // send Higher address byte
 I2C1_Wr(rAddrL);          // send Lower address byte
 I2C1_Repeated_Start();    // issue I2C1 signal repeated start
 I2C1_Wr(EEPROM_Select+1);  // send byte (device address + R)
 result = I2C1_Rd(0u);    // Read the data (NO acknowledge)
 while (!I2C1_Is_Idle())
 asm nop;                // Wait for the read cycle to finish
 I2C1_Stop();
 return result;
}
//--------------- Writes data to 24LC512 EEPROM - single location
void EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {
 unsigned short wAddrH, wAddrL;
 wAddrH = 0;
 wAddrL = wAddress;
 I2C1_Start();        // issue I2C1 start signal
 I2C1_Wr(DeviceSelect);  // send control byte
 I2C1_Wr(wAddrH);    // send higher address byte
 I2C1_Wr(wAddrL);    // send lower address byte
 I2C1_Wr(wData);      // send data to be written
 I2C1_Stop();
}
 


كود البرنامج :
الكود:
 
/*
  Project: Multiple I2C devices on a common bus
  MCU: PIC18F2550 @ 48.0 MHz (StartUSB for PIC board)
  Copyright @ Rajendra Bhatt
  May 6, 2011
*/

// Define LCD module connections.
 sbit LCD_RS at RC6_bit;
 sbit LCD_EN at RC7_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 TRISC6_bit;
 sbit LCD_EN_Direction at TRISC7_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 connection definition


void Delay2s(){
 Delay_ms(2000);
}

void check_device(unsigned short dev_address){
 I2C1_Start();
 if (I2C1_Wr(dev_address)){
  Lcd_Out(2,1,"Device not found");
 }
 else Lcd_Out(2,1,"Device is OK");
 I2C1_Stop();
}

//--------------- Writes data to 24LC512 EEPROM - single location
void EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {
    unsigned short wAddrH, wAddrL;
    wAddrH = 0;
    wAddrL = wAddress;
    I2C1_Start();        // issue I2C1 start signal
    I2C1_Wr(DeviceSelect);  // send control byte
    I2C1_Wr(wAddrH);    // send higher address byte
    I2C1_Wr(wAddrL);    // send lower address byte
    I2C1_Wr(wData);      // send data (data to be written)
    I2C1_Stop();
}
//--------------- Reads data from 24LC512 EEPROM - single location
unsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {
    unsigned short rAddrH, rAddrL, result;
    rAddrH = 0;
    rAddrL = rAddress;
    I2C1_Start();            // issue I2C1 start signal
    I2C1_Wr(EEPROM_Select);  // send byte via I2C1  (device address + W)
    I2C1_Wr(rAddrH);          // send Higher address byte
    I2C1_Wr(rAddrL);          // send Lower address byte
    I2C1_Repeated_Start();    // issue I2C1 signal repeated start
    I2C1_Wr(EEPROM_Select+1);            // send byte (device address + R)
    result = I2C1_Rd(0u);    // Read the data (NO acknowledge)
    while (!I2C1_Is_Idle())
      asm nop;                // Wait for the read cycle to finish
    I2C1_Stop();
    return result;
}

char message1[] = "I2C Devices ";
char message2[] = "with PIC18F2550" ;
char Sample[] = "Sample 0";
char temp[] = "00.0000 C";

unsigned int address, Fraction_Temp;
unsigned short i,MS_Byte, LS_Byte, Whole_Temp;
const int EEPROM1 = 0xA0, EEPROM2 = 0xA2, DS1631 = 0x90;
void main() {
  CMCON = 0x07;  // Disable comparators
  ADCON1 = 0x0F;  // Disable Analog functions
  TRISC = 0x00;
  TRISB = 0x00;
  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
  Lcd_Out(2,1,message2);  // Write message1 in 1st row
  Delay2s();

  I2C1_Init(100000);  // Initiate I2C

  // Check EEPROM1
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"EEPROM1");
  check_device(EEPROM1);
  Delay2s();
 
  // Check EEPROM2
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"EEPROM2");
  check_device(EEPROM2);
  Delay2s();
 
  // Check Sensor
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1,"DS1631");
  check_device(DS1631);
  Delay2s();

  for (i=0; i<5; i++) {
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Reading Temp.");
    // Read temperature
    I2C1_Start();
    I2C1_Wr(DS1631);              // Send device address
    I2C1_Wr(0x51);                // Start Convert Temp command
    I2C1_Stop();
    Delay_ms(750);
    I2C1_Start();
    I2C1_Wr(DS1631);              // DS1631 Address again
    I2C1_Wr(0xAA);                // Read Temperature command
    I2C1_Repeated_Start();
    I2C1_Wr(DS1631+1);              // Address with Read
    MS_Byte = I2C1_Rd(1);          // Read MSB and send ACK
    LS_Byte = I2C1_Rd(0);            // Read LSB and send NAK
    I2C1_Stop();
    Delay2s();

    // Write the MS Byte to EEPROM1
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Writing MS Byte");
    EEPROM_WriteByte(EEPROM1, i, MS_Byte);
    Delay2s();

    // Write the LS Byte to EEPROM2
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Writing LS Byte");
    EEPROM_WriteByte(EEPROM2, i, MS_Byte);
    Delay2s();
  }
    // Reading stored temperature samples
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Reading EEPROMs");
    Delay2s();

    for (i=0; i<5; i++){
    Lcd_Cmd(_LCD_CLEAR);
    Sample[7] = i+49; //"Sample 1","Sample 2",……,"Sample 5"
    Lcd_Out(1,1,Sample);
    Whole_Temp = EEPROM_ReadByte(EEPROM1, i);
    Fraction_Temp = EEPROM_ReadByte(EEPROM2, i);
    Fraction_Temp = Fraction_Temp >>4;
    Fraction_Temp = 625*Fraction_Temp; // 12 bit resolution is 0.0625C
    temp[0] = Whole_Temp/10+48;
    temp[1] = Whole_Temp%10+48;
    temp[3] = Fraction_Temp/1000+48;
    temp[4] = (Fraction_Temp/100)%10+48;
    temp[5] = (Fraction_Temp/10)%10+48;
    temp[6] = Fraction_Temp%10+48;
    Lcd_Out(2,5,temp);
    Delay2s();
    }

  }


Admin
Admin

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

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

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

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

مُساهمة من طرف Admin في الخميس يوليو 13, 2017 12:55 pm

التحويل من تناظرى لرقمى ADC
مقدمة :
العديد من الإشارات الكهربائية من حولنا تكون ذات طبيعة تناظرية Analog (تتغير قيمتها بشكل مستمر) . محولات حساسات الكميات الطبيعية فى الغالب تحول الكمية الطبيعية إلى إشارة كهربائية ، هذا يعنى أن كمية تتغير مباشرة مع كمية أخرى . الكمية الأولى فى الغالب تكون الجهد voltage فى حين أن الكمية الثانية يمكن أن تكون أى كمية طبيعية مثل درجة الحرارة ، الضغط ، الضوء ، القوة ، العجلة ، .... إلخ . على سبيل المثال ، فى حساس درجة الحرارة LM35 ، جهد خرجه يتغير تبعا لدرجة الحرارة ، ومن ثم إذا امكننا قياس الجهد ، يمكنننا قياس درجة الحرارة .

ولكن معظم أجهزة الكمبيوتر (أو الميكروكنترولر) تكون ذات طبيعة رقمية. فهى يمكن أن تفرق فقط بين المستوى المرتفع HIGH أو المستوى المنخفض LOW على أطراف الدخل . على سبيل المثال ، إذا كان الدخل أكبر 2.5V سيتم قراءته باعتباره واحد (1) ، وإذا كان الدخل أقل من 2.5V سيتم قراءته باعتباره صفر (0) ( فى الأنظمة التى تعمل على 5V ) . لذلك لا يمكننا قياس الجهد مباشرة من الميكروكونترولر . لحل هذه المشكلة ، معظم الميكروكونترولر يمتلك وحدةتحويل من تناظرى إلى رقمى ADC . هذا المحول سوف يقوم بتحويل الجهد voltage إلى عدد number بحيث يمكن معالجته من قبل الأنظمة الرقمية مثل الميكروكونترولر . هذا المحول يتيح لنا ربط بسهولة كل أنوع الأجهزة التناظرية مع الميكروكونترولر .
دقة المحول من تناظرى لرقمى Resolution :
إن أهم مواصفات المحول من تناظرى لرقمى ADC هي "الدقة أو القدرة على التحليل " resolution ( هى أقل كمية يمكن قياسها ) . وهى تحدد مدى دقة قياس ADC لإشارات المدخلات التناظرية. نتيجة تحويل المحولات الشائعة تكون بسعة 8-bit أو 10-bit أو 12-bit . على سبيل المثال إذا كان جهد المرجع (سوف يتم شرحه لاحقا ) لمحول ADC هو من 0V إلى 5V ، فإن المحول 8-bit سوف يقسمه إلى 256 قسم ( من 0 إلى 255 ) ، لذلك يمكنه القياس بدقة ( تغيير نتيجة التحويل بمقدار واحد قسم ) تصل إلى 5/255 V =19.6mV تقريبا. في حين أن المحول 10-bit سوف يقسمه إلى 1024 قسم (أدنى نتيجة تحويل هى 0 ، وأقصى نتيجة تحويل هى 1023 ) ، عندئذ تكون دقة القياس
5/1023 V = 4.88 mV تقريبا . من ذلك يمكنك أن تدرك أن المحول 8-bit لا يمكنه التفرقة بين 1mV و 18mV .
المحول ADC المدمج فى الميكروكونترولر PIC من نوع 10-bit .



مصطلح الجهد المرجعى Reference Voltage :
الجهد المرجعى يحدد الحد الأدنى والحد الأقصى لمدى جهد الدخل التناظرى . فى الميكروكونترولر PIC يوجد جهدى مرجع ، إحداهما هو جهد المرجع السالب Vref- ، والآخر هو جهد المرجع الموجب Vref+ . جهد المرجع السالب Vref- يحدد الحد الأدنى لجهد الدخل التناظرى ، فى حين أن جهد المرجع الموجب يحدد الحد الأقصى لجهد الدخل التناظرى . على سبيل المثال ، إذا تم تطبيق إشارة قيمتها Vref- على قناة الدخل التناظرى ، عندئذ تكون نتيجة التحويل بصفر ، وإذا تم تطبيق إشارة قيمتها Vref+ على قناة الدخل التناظرى ، فإن النتيجة سوف تكون 1023 ( أقصى قيمة للمحول ADC ) .
• عندما يكون دخل ADC بقيمة Vref- ، فإن نتيجة التحويل تكون 0000000000 .
• وعندما يكون دخل ADC بقيمة Vref+ ، فإن نتيجة التحويل تكون 1111111111 .
• دقة ADC

الكود:
 Resolution of ADC = (Vref+ – Vref-)/(210 – 1) 


وهى أدنى جهد مطلوب لتغيير نتيجة تحويل ADC بواحد بت .
• فى الحالة العادية الافتراضية Resolution = (5 – 0)/(1024 – 1) = 5/1023 = 0.004887V .
• لذلك ، إذا كان الدخل 5V ، فإن نتيجة تحويل ADC تكون 5/0.004887 = 1023 = 11111111 (binary .
• وإذا كان الدخل 0.004887V ، فإن نتيجة تحويل ADC تكون 0.004887/0.004887 = 1 = 00000001 (binary) .
باختصار ، يمكن القول ، بأن قياس الجهد فى المحول يستند على مقارنة جهد الدخل مع المقياس الداخلى والذى له 1024 علامة (قسم) (2 أس عشرة) . أدنى علامة للمقياس تناظر جهد المرجع السالب Vref- ، فى حين أن أعلى علامة للمقياس تناظر جهد المرجع الموجب . الشكل التالى يبين جهدى المرجع القابلة للاختيار وقيمها الدنيا والقصوى أيضا .



معظم الميكروكونترولر PIC تمتلك ضمن بنائها موديول ADC . سوف نستعرض الميكروكونترولر PIC16F877A ، على سبيل المثال . الميكروكونترولر PIC16F877A يمتلك موديول 10-bit ADC .
جهد المرجع الموجب Vref+ وجهد المرجع السالب Vref- تكون قابلة للبرمجة ، فهى يمكن أن تكون VDD,VSS أو جهد ما على الأطراف RA2,RA3 .



موديول ADC يعمل مع أى من ثمانى قنوات متصلة بالأطراف الخارجية ، يتم الاختيار بين القنوات برمجيا عن طريق بتات اختيار القناة CHS0:CHS2 بالسجل ADCON0 (مترجم الميكروسى برو يقوم نيابة عنك بذلك )، كما هو مبين بالشكل .



السجل ADCON1 يتحكم فى تهيئة المنافذ لتكون تناظرية أو رقمية أو توليفة من الاثنين معا ، حيث يمكن تهيئة أى من الأطراف AN0-AN7 كمدخل تناظرى أو مدخل لجهد مرجع أو دخل / خرج رقمى ، وذلك عن طريق بتات تهيئة المنفذ PCFG0:PCFG3 ، كما هو موضح بالشكل .



الجدول التالى يبين الخيارات الممكنة :



ملاحظات :
1- فى الوضع الافتراضى البتات الأربعة تكون بأصفار وهذا يعنى أن جميع المداخل هى مداخل تناظرية وأن جهد المرجع الموجب يساوى VDD ، وجهد المرجع السالب هو VSS . يجب ألا تنسى تهيئة طرف المدخل التناظرى كطرف دخل عن طريق السجل TRIS (مع العلم بأن الوضع الافتراضى لتهيئة جميع المنافذ هو مداخل ) . الشكل أدناه يبين المخطط الصندوقى لموديول ADC .
2- اختيار ADCON=6 يعنى تهيئة جميع الأطراف باعتبارها مداخل / مخارج رقمية .



للتعامل مع المحول ADC ، فإن مترجم الميكروسى برو لديه مكتبة تعرف باسم ADC لإجراء التحويل . هذه المكتبة بها دالة وحيدة هى :

الكود:
unsigned ADC_Read(unsigned short channel);

هذه الدالة تعود بنتيجة التحويل 10-bit للقناة المحددة بواسطة البارامتر channel .
مثال:
للتدريب على استخدام هذه المكتبة راقب وحلل المثال التالى :

الكود:
 void main (void)
{
   // Declaration of variables.
   unsigned int ADC_result; 
   // Initialize ports.
   TRISB = 0;
   TRISC = 0;
   PORTB = 0;
   PORTC = 0;
   while (1)             // infinite loop.
   {
      ADC_result = ADC_Read (0);    // conversion is made on channel 0.
      //  Display 8 least significant bits from  port B.
      PORTB = ADC_result &0xFF;
      //Display  the most significant 2 bits from the port C.
      PORTC = (ADC_result >> 8) &0x03;
   }
}

لمحاكاة هذا البرنامج يجب جلب الأجهزة الآتية فى برنامج ISIS :
16F877A, RES, LEDRED,POT-HG
الشكل التالى يبين الدائرة الكهربية :



بعد تشغيل المحاكاة تعرض الليدات نتيجة قيمة التحويل فى شكل كود ثنائى binary code ، لفرق الجهد التناظرى المغذى بواسطة المقاومة المتغيرة .

Admin
Admin

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

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

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

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

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

تدريب تمهيدى :
الغرض :
استعراض التعامل مع المحول 10-bit ADC باستخدام الميكروكونترولر PIC16F877A . جهد دخل المحول ADC يتم أخذه من مقاومة متغيرة 5K متصلة بالجهد +5V ، ويتم توصيله إلى الطرف RA0/AN0 مع أخذ جهدى المرجع الافتراضية VDD,VSS(0-5V) ، وبالتالى يكون مدى التحويل ADC من 0 إلى 1023 . سوف يتم عرض نتيجة التحويل على شاشة LCD .
الدائرة الكهربية :



البرنامج :

الكود:
// 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[] = "ADC Value= ";
 char *temp = "0000";
 unsigned int ADC_Value;
 void main() {
  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 {
  adc_value = ADC_Read(0);
  temp[0] = adc_value/1000 + 48; // Add 48 to get the ASCII character value
  temp[1] = (adc_value/100)%10 + 48;
  temp[2] = (adc_value/10)%10 + 48;
  temp[3] = adc_value%10 + 48;
  Lcd_Out(1,11,temp);
  Delay_ms(2000);
  } while(1);
 }


مشروع جهاز قياس الجهد (فولتميتر) ، وجهاز قياس تيار (أمبيرميتر) باستخدام الميكروكونترولر PIC :
يمكن بسهولة صنع فولتميتر وأمبير ميتر باستخدام ميكروكونترولر PIC لديه موديول محول من تناظرى لرقمى ADC . سوف نستخدم الميكروكونترولر PIC16F877A ، وعرض النتيجة على وحدة عرض LCD .
موديول ADC يحول الإشارات التناظرية المطبقة على طرفه التناظرى إلى عدد ثنائى 10-bit ، وله القدرة على اختيار جهد المرجع الموجب وجهد المرجع السالب بالجهد VDD,VSS أو بجهد على الأطراف RA2,RA3 .
الدخل التناظرى إلى الميكروكونترولر PIC محدد بالجهود VDD,VSS(0-5V) التى تغذى الميكروكونترولر PIC .
فى هذا المشروع سوف يتم قياس الجهد فى المدى 0-50V ، ولتخفيضه ليكون فى مدى الميكرونترولر PIC (0-5V) فسوف نستخدم مقسم جهد مناسب .
يتم قياس تيار الحمل عن طريق تمريره خلال مقاومة صغيرة وقياس فرق الجهد بين طرفيها (محول تيار إلى جهد) ، كما هو مبين بالشكل أدناه .







يتم توصيل خرج مقسم الجهد إلى الطرف RA2 ، وتوصيل الجهد عبر مقاومة قياس التيار إلى الطرف RA3 ، كما يتم توصيل هذين الطرفين بزنر دايود 5.1V لحماية الميكروكونترولر من ارتفاع الجهد .
الحسابات :
حسابات الجهد :
جهد دخل الميكروكونترولر التناظرى Vpicv حيث :

الكود:
Vpicv = ADC_result(5/1023) = 0.00489 ADC_result
 Vpicv = 4.89 ADC_result mV 

وهو نفسه جهد خرج مقسم الجهد ، ومن ثم يكون :

الكود:
4.89 ADC_result = Vin (1.1/11.1)
Vin = 4.89 ADC_result * (11.1/1.1)
Vin=49.34 ADC_result mV 

أى للحصول على جهد الدخل يتم ضرب نتيجة التحويل ADC فى 49.34 .
حسابات التيار :
بالمثل ، جهد دخل الميكروكونترولر التناظرى الواصل إلى الطرف RA3 والناتج عن مرور تيار الحمل فى مقاومة القياس Vpici حيث :

الكود:
 Vpici = ADC_result(5/1023) = 4.89 ADC_result mV

التيار المارفى مقاومة القياس يكون :

الكود:
Iin = 4.89 ADC_result / 0.1 = 48.9 ADC_result mA 

أى للحصول على تيار الدخل يتم ضرب نتيجة التحويل ADC ، لهذه الحالة ، فى 48.9
ملحوظة :
مدى جهد الدخل أصبح من 0 إلى 50000 ملى فولت ، وصيغته تكون بالشكل00.0 ( خانة عشرات ، وخانة آحاد ، وخانة كسر عشرى) ، ومن ثم لاستخلاص رقم خانة العشرات فسوف يتم القسمة على 10000 ولاستخلاص رقم خانة الآحاد فسوف يتم القسمة على 1000 يتبعه إيجاد باقى خارج قسمة الناتج على 10 ، وهكذا . بالنسبة للتيار تكون صيغته 0.00 (خانة آحاد وخانتى كسر عشرى ) أى له رقم خانة آحاد فقط ، يمكن استخلاصة بالقسمة على 1000 .

البرنامج :

الكود:

// 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 int v,i;
  char *volt = "00.0";
  char *current = "0.00";

void main()
{
 
  CMCON = 0x07;
  TRISA = 0xFF;
  ADCON1 = 0x00;
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Cmd(_LCD_CURSOR_OFF);

  do
  {
    v = ADC_Read(2);
    i = ADC_Read(3);
    v = 49.34  * v ;
    i = 48.9  * i ;

    volt[0] = (v/10000)+48;
    volt[1] = ((v/1000)%10)+48;
    volt[3] = ((v/100)%10)+48;
    Lcd_Out(1,1,"Voltage = ");
    Lcd_Out(1,11,volt);
    Lcd_Out(1,16,"V");

    current[0] = (i/1000)+48;
    current[2] = ((i/100)%10)+48;
    current[3] = ((i/10)%10)+48;
    Lcd_Out(2,1,"Current = ");
    Lcd_Out(2,11,current);
    Lcd_Out(2,16,"A");
    Delay_ms(250);
  } while(1);
}
 

Admin
Admin

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

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

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

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

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

أجهزة الاستشعار (الحساسات) Sensors
استخدام أجهزة الاستشعار فى أنظمة الميكروكونترولر مفيد للغاية فى الكثير من التطبيقات حيث أنها تتيح الحصول على قراءات (قياسات) لكميات طبيعية مثل درجة الحرارة والعجلة والسرعة والضغط والرطوبة وشدة الإضاءة وغيرها الكثير. هذه التطبيقات مهمة فى أنظمة التحكم وفى الروبوتات وأجهزة القياس .
جهاز استشعار درجة الحرارة LM35 :
الحساس LM35 هو جهاز فعال ذو ثلاثة أطراف يسمح بتحصيل درجة حرارة الوسط المحيط (البيئة) فى المدى من -55 إلى 150 درجة مئوية . يسهل تنفيذ التطبيقات بهذا الحساس لأن لديه فقط طرفين للتغذية وطرف لجهد الخرج والذى يتناسب مباشرة مع درجة الحرارة . يمكن تغذية هذا الحساس من مصدر جهد يتراوح بين 4 - 30 volts وخرجه يكون بقيمة 10 ملى فولت لكل درجة مئوية . الشكل التالى يبين مظهر الحساس الطبيعى ورمزه فى برنامج إيزيس :



لتنفيذ قراءة جهد خرج الحساس باستخدام الميكروكونترولر يتم استخدام موديول التحويل من تناظرى لرقمى ADC module . أقصى جهد خرج للحساس هو 1.5 volts ، عندما تكون درجة الحرارة 150 درجة مئوية. لذلك من المهم تغيير جهد المرجع الموجب للمحول من تناظرى لرقمى ، بغرض تحسين دقة قياس الجهد . فى المثال المذكور أدناه سوف يتم تحديد جهد المرجع الموجب Vref+ للمحول ADC بالقيمة 2.5 volts . بهذه الطريقة ، عندما يكون جهد الدخل التناظرى 2.5 volts فإن نتيجة التحويل من تناظرى لرقمى المناظرة تكون العدد 1023 . يمكن التعبير عن هذا المفهوم بالصيغة التالية :

الكود:
Vpic = ADC_result * (2.5/1023) = 2.44 * ADC_result mV 

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

الكود:
Vout = 10 * Tc mV

بمساواة المعادلتين يمكن الحصول على درجة الحرارة كما يلى :

الكود:
Tc = (2.44 * ADC_result) / 10 = 0.244 * ADC_result

أى للحصول على درجة الحرارة بالدرجة المئوية يتم ضرب نتيجة التحويل ADC_result فى العامل 0.244 .
يجب استخدام هذه المعادلة عند تنفيذ التحويل من تناظرى لرقمى فى برنامج الميكروكونترولر PIC .
فى هذا الإطار يمكن استخدام الحساس والميكروكونترولر PIC16F877A فى تنفيذ البرنامج ، وفيما يلى كود البرنامج :

الكود:

// 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, TemI;
   float Tem;
   char Text[16];

void main( void )
{
   
   //Sets the ADC module with pin AN3
   //as positive reference voltage.
   ADCON1 = 0b11000001;
   //LCD initiation
   Lcd_Init();
   //Clearing the cursor.
   Lcd_Cmd(_LCD_CURSOR_OFF);
   //Printing text.
   Lcd_Out( 1, 1, "Temperature :");
   while(1) //Infinite Loop.
   {
      //Reading ADC channel 0.
      Radc = ADC_Read(0);
      //Using the equation
      Tem = 0.244*Radc;
      //Converts the result to an integer.
      TemI = Tem;
      //Integer converted to a string.
      IntToStr( TemI, Text );
      //Prints the result.
      Lcd_Out( 2, 1, Text);
      //Delay 100m  seconds.
      delay_ms(100);
   }
}
 

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




المقاومتان 330Ω يعملان كمقسم جهد للحصول على جهد المرجع بالقيمة 2.5 volts . خلال المحاكاة يمكنك تغيير قيمة درجة حرارة الحساس LM35 ومشاهدة النتيجة .

Admin
Admin

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

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

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

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

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

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

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