Bài viết này sẽ hướng dẫn các bạn quét bàn phím (keypad) 4×4 và hiển thị ký tự được ấn lên LCD 16×2, vi điều khiển mình sử dụng là PIC16F877 và IDE sử dụng là PIC C Compiler 5.048. Sơ đồ mạch các bạn xem ở hình dưới.

Code PIC16F877
main.c
/** @uthor https://nvtienanh.info @brief Demo Keypad and LCD PIC16F877 */ #include <16f877.h> #device *=16 adc=10 #fuses hs, nowdt, noprotect, nolvp, put, brownout #use delay(clock=20000000) #include <lcd.h> #include <Keypad.h> #include <function_lcd.c> #include <Keypad.c> // 4-Bits Interface void main() { unsigned char line1[16], line2[16]; char Key = 'n'; // Variable to store pressed key value InitKeypad(); // Initialize Keypad pins LCD_Init(); delay_ms(10); sprintf(line1," DEMO KEYPAD "); sprintf(line2," nvtienanh.com "); LCD_Gotoxy(0,0); LCD_Puts(line1); LCD_Gotoxy(1,0); LCD_Puts(line2); while(TRUE) { Key = GetKey(); LCD_Clear(); LCD_Gotoxy(0,0); LCD_PutChar(Key); LCD_Gotoxy(1,0); LCD_Puts(line2); //delay_ms(500); } }
lcd.h
#define _LCD_ #define LCD_RS PIN_D1 #define LCD_RW PIN_D2 #define LCD_EN PIN_D0 #define LCD_D4 PIN_D4 #define LCD_D5 PIN_D5 #define LCD_D6 PIN_D6 #define LCD_D7 PIN_D7 #endif
Keypad.h
#ifndef __KEYPAD_H #define __KEYPAD_H // Define pins #define RowA PIN_B0 #define RowB PIN_B1 #define RowC PIN_B2 #define RowD PIN_B3 #define C1 PIN_B4 #define C2 PIN_B5 #define C3 PIN_B6 #define C4 PIN_B7 #define Keypad_PORT PORTB #define Keypad_PORT_Dir TRISB // Function declarations void InitKeypad(void); char GetKey(void); #endif
function_lcd.c
/** @uthor https://bmshop.vn @brief LCD functions */ void LCD_Enable(void) { output_high(LCD_EN); delay_us(3); output_low(LCD_EN); delay_us(50); } //Ham Gui 4 Bit Du Lieu Ra LCD void LCD_Send4Bit( unsigned char Data ) { output_bit(LCD_D4,Data&0x01); output_bit(LCD_D5,(Data>>1)&1); output_bit(LCD_D6,(Data>>2)&1); output_bit(LCD_D7,(Data>>3)&1); } // Ham Gui 1 Lenh Cho LCD void LCD_SendCommand (unsigned char command ) { LCD_Send4Bit ( command >>4 );/* Gui 4 bit cao */ LCD_Enable () ; LCD_Send4Bit ( command ); /* Gui 4 bit thap*/ LCD_Enable () ; } void LCD_Init (void) { output_low(LCD_RS); output_low(LCD_RW); delay_ms(20); LCD_Send4Bit(0x03); LCD_Enable(); delay_ms(10); LCD_Send4Bit(0x03); LCD_Enable(); delay_ms(10); LCD_Send4Bit(0x03); LCD_Enable(); delay_ms(10); LCD_Send4Bit(0x02); LCD_Enable(); delay_ms(10); LCD_SendCommand( 0x28 ); // giao thuc 4 bit, hien thi 2 hang, ki tu 5x8 //Function Set: 8-bit, 1 Line, 5x7 Dots 0x30 //Function Set: 8-bit, 2 Line, 5x7 Dots 0x38 //Function Set: 4-bit, 1 Line, 5x7 Dots 0x20 //Function Set: 4-bit, 2 Line, 5x7 Dots 0x28 LCD_SendCommand( 0x0C); //Display on Cursor on: 0x0E 0x0F //Display on Cursor off: 0x0C //Display on Cursor blinking: 0x0F LCD_SendCommand( 0x06 ); // tang ID, khong dich khung hinh Entry Mode LCD_SendCommand( 0x01 ); // Clear Display (also clear DDRAM content) } void LCD_PutChar ( unsigned char Data ) { output_high(LCD_RS); LCD_SendCommand( Data ); output_low(LCD_RS); } void LCD_Puts (char *s) { while (*s) { LCD_PutChar(*s); s++; } } void LCD_Clear() { LCD_SendCommand(0x01); delay_ms(10); } void LCD_Gotoxy(unsigned char row, unsigned char col) { unsigned char address; if(!row) address = (0x80 + col); else address = (0xC0 + col); delay_us(500); LCD_SendCommand(address); delay_us(50); }
Keypad.c
#include "Keypad.h" // Function name: InitKeypad void InitKeypad(void) { output_b(0x00); // Set Keypad port pin values zero set_tris_b(0xF0); // Last 4 pins input, First 4 pins output port_b_pullups (0x7F);// Enable weak internal pull up on input pins } // Function name: READ_SWITCHES // Scan all the keypad keys to detect any pressed key. char READ_SWITCHES(void) { output_low(RowA); output_high(RowB); output_high(RowC); output_high(RowD); //Test Row A if (input_state(C1) == 0) { delay_ms(250); while (input_state(C1)==0); return '7'; } if (input_state(C2) == 0) { delay_ms(250); while (input_state(C2)==0); return '8'; } if (input_state(C3) == 0) { delay_ms(250); while (input_state(C3)==0); return '9'; } if (input_state(C4) == 0) { delay_ms(250); while (input_state(C4)==0); return '/'; } //RowA = 1; RowB = 0; RowC = 1; RowD = 1; //Test Row B output_high(RowA); output_low(RowB); output_high(RowC); output_high(RowD); if (input_state(C1) == 0) { delay_ms(250); while (input_state(C1)==0); return '4'; } if (input_state(C2) == 0) { delay_ms(250); while (input_state(C2)==0); return '5'; } if (input_state(C3) == 0) { delay_ms(250); while (input_state(C3)==0); return '6'; } if (input_state(C4) == 0) { delay_ms(250); while (input_state(C4)==0); return 'x'; } // RowA = 1; RowB = 1; RowC = 0; RowD = 1; //Test Row C output_high(RowA); output_high(RowB); output_low(RowC); output_high(RowD); if (input_state(C1) == 0) { delay_ms(250); while (input_state(C1)==0); return '1'; } if (input_state(C2) == 0) { delay_ms(250); while (input_state(C2)==0); return '2'; } if (input_state(C3) == 0) { delay_ms(250); while (input_state(C3)==0); return '3'; } if (input_state(C4) == 0) { delay_ms(250); while (input_state(C4)==0); return '-'; } //RowA = 1; RowB = 1; RowC = 1; RowD = 0; //Test Row D output_high(RowA); output_high(RowB); output_high(RowC); output_low(RowD); if (input_state(C1) == 0) { delay_ms(250); while (input_state(C1)==0); return 'C'; } if (input_state(C2) == 0) { delay_ms(250); while (input_state(C2)==0); return '0'; } if (input_state(C3) == 0) { delay_ms(250); while (input_state(C3)==0); return '='; } if (input_state(C4) == 0) { delay_ms(250); while (input_state(C4)==0); return '+'; } return 'n'; // Means no key has been pressed } // Function name: GetKey // Read pressed key value from keypad and return its value char GetKey(void) // Get key from user { char key = 'n'; // Assume no key pressed while(key=='n') // Wait untill a key is pressed key = READ_SWITCHES(); // Scan the keys again and again return key; //when key pressed then return its value }
Video demo