E' noto che per utilizzare un LCD, tutti i pin connessi al modulo alfanumerico devono essere impostati come uscite, mentre per il pilotaggio di una tastiera solo i pin connessi alle colonne devono essere impostati come uscita e quelli connessi alle righe devono essere ingressi. Questi ultimi devono essere connessi anche ad un pull-up resistivo che può essere costituito da resistori esterni da 10K o dal pull-up interno del microcontrollore (se disponibile). L’accorgimento per gestire entrambi i dispositivi è piuttosto elementare: durante la gestione della tastiera si mantiene a livello basso il pin Enable del modulo LCD in modo da disattivare il display. Lo schema è riportato in figura 1, mentre il listato 1 riporta il sorgente scritto in mikroC.
#include “lcd_keypad.h” void init_ports(void) { ADCON1 = 0x06; //tutte uscite digitali PORTB = 0; TRISB = 0; //PORTB come uscite } void main() { unsigned short key ; //tasto premuto unsigned short c=0 ; // Show something on LCD. char op[4] ; // Scratch area. init_ports(); LCD_access(); Lcd_Config(&PORTB,0,2,1,7,6,5,4); // PORT,RS,EN,WR,D7,D6,D5,D4 Lcd_Cmd(Lcd_CLEAR);// Clear display Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off Lcd_Out(1, 1, “BEST-MICRO-PJCTS”); // Print text to LCD, 2nd row, 1st column for(;;) { // lettura KEYPAD key = read_KEYPAD(); //decodifica del tasto premuto e conversione in carattere switch (key) { case KEY_0 : key=’0’;break; case KEY_1 : key=’1’;break; case KEY_2 : key=’2’;break; case KEY_3 : key=’3’;break; case KEY_4 : key=’4’;break; case KEY_5 : key=’5’;break; case KEY_6 : key=’6’;break; case KEY_7 : key=’7’;break; case KEY_8 : key=’8’;break; case KEY_9 : key=’9’;break; case KEY_STAR : key=’*‘;break; case KEY_HASH : key=’#‘;break; } LCD_access(); // Uso del display if (key) LCD_Chr(2,15,key); //Visualizza il tasto premuto: ByteToStr(c++,op); Lcd_Out(2, 1, op); } }
Listato 1 |
Il programma mette a livello basso alternativamente tutte le colonne della tastiera a matrice. Quando viene premuto un tasto, lo zero presente sulla colonna viene trasmesso sulla riga su cui è connesso il tasto. Se nessun tasto è premuto, tutte le righe saranno a livello alto. La routine di lettura della tastiera ritorna un intero secondo quanto definito nel file lcd_key.h (riportato nel listato 2).
#define LCD_ALL (LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7 | LCD_RS | LCD_R_W | LCD_E) // Keypad PINS #define KEY_ROW1 (1<<4) #define KEY_ROW2 (1<<5) #define KEY_ROW3 (1<<7) #define KEY_ROW4 (1<<6) #define KEY_COL1 (1<<0) #define KEY_COL2 (1<<1) #define KEY_COL3 (1<<3) // Keypad groups #define KEY_ROWS (KEY_ROW1 | KEY_ROW2 | KEY_ROW3 | KEY_ROW4) #define KEY_COLS (KEY_COL1 | KEY_COL2 | KEY_COL3) #define KEY_ALL (KEY_ROWS | KEY_COLS) ///////////////////////////////////////////////////////////////////// // Output key values. // // These are only valid for the correct hardware connections // RB4=Row1(top), RB5=Row2, RB6=Row3, RB7=Row4 // RB0=COL1(left),RB1=COL2, RB3=COL3 // #define KEY_1 225 #define KEY_2 226 #define KEY_3 232 #define KEY_4 209 #define KEY_5 210 #define KEY_6 216 #define KEY_7 177 #define KEY_8 178 #define KEY_9 184 #define KEY_STAR 113 #define KEY_0 114 #define KEY_HASH 120 // Prototypes void LCD_access(void);
Listato 2 |
Premendo due tasti connessi a differenti righe e colonne, vengono cortocircuitate due colonne che si trovano a livelli differenti. Poiché il pilotaggio delle colonne viene attraverso tre resistenze in serie (R1, R2 e R3), questo fenomeno non recherà alcun danno al circuito e consente, allo stesso tempo, di gestire correttamente il display anche se qualche tasto risulta premuto. Il listato 3 mostra le routnines LCD_access per abilitare il display, KEYPAD_access per abilitare la tastiera, e READ_keypad che legge il tasto premuto e lo converte nell’opportuno carattere.
unsigned short read_KEYPAD(void); void LCD_access(void) { LCD_PORT = 0; LCD_TRIS = ~LCD_ALL; } static void KEYPAD_access(void) { KEY_PORT = 0x00; KEY_TRIS = ~KEY_COLS &~(LCD_E); } unsigned short read_KEYPAD(void) { unsigned short mask = KEY_COL1; unsigned short val; unsigned short i; char op[9]; KEY_PORT = 0x00; KEY_TRIS = ~KEY_COLS &~(LCD_E); OPTION_REG &= 0x7f; // enable portb pullups. for (i=0;i<3;i++) { if (mask==LCD_E) mask <<=1; KEY_PORT = ~mask & ~(LCD_E); delay_us(500); val = (KEY_PORT & KEY_ROWS); if ( (val & KEY_ROWS) != KEY_ROWS) { return (val & KEY_ROWS) | mask; } mask = mask << 1; } return 0; // no keys return zero }
Listato 3 |
Un interessante circuito per testare tastiera e display con un MCU. E’ possibile attivare attraverso la tastiera alcuni sistemi, facendo un check dal display.