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

   

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 21-06-2017, 02:33 PM المشاركة 97   
افتراضي



تدريب رقم 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 
}

اعلانات

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 21-06-2017, 02:38 PM المشاركة 98   
افتراضي


تدريب رقم 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();
    }
  }
}

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

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 21-06-2017, 02:55 PM المشاركة 99   
افتراضي


مشروع عد وعرض ومعالجة عدد الأشياء تصاعديا وتنازليا باستخدام 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
}


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 21-06-2017, 03:32 PM المشاركة 100   
افتراضي


الحروف المخصصة (التفصيل) 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);


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 21-06-2017, 03:53 PM المشاركة 101   
افتراضي


تدريب :





الخطوات :
• تحديد حجم الخط 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);
}


الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 24-06-2017, 02:40 AM المشاركة 102   
افتراضي


استخدام مصفوفة لوحة المفاتيح 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.
 	}
 }
بمجرد التحرير يتم الترجمة والمحاكاة حيث يعرض على الشاشة الحرف المقابل للمفتاح المضغوط بلوحة المفاتيح كما فى الشكل التالى :






التعديل الأخير تم بواسطة : F.Abdelaziz بتاريخ 24-06-2017 الساعة 02:48 AM

الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 24-06-2017, 02:41 PM المشاركة 103   
افتراضي


تدريب تمهيدى 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);
}
النتيجة :




الصورة الرمزية F.Abdelaziz
F.Abdelaziz
:: استاذ و مشرف قسم الالكترونيات ::
تاريخ التسجيل: May 2007
المشاركات: 6,832
نشاط [ F.Abdelaziz ]
قوة السمعة:
قديم 24-06-2017, 04:30 PM المشاركة 104   
افتراضي


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



لوحة المفاتيح الرقمية تستخدم فى كثير من المجالات ، من أنظمة الأمان وحتى التليفونات المحمولة . فى هذا المشروع سوف نستخدم لوحة مفاتيح 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,"____");
		}
	}
}
}
النتيجة :







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