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.

Sơ đồ mạch nguyên lý trên Proteus
Code PIC16F877
/**
@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 ;
#include ;
#include ;
#include ;
// 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);
}
}
#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
#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
/**
@uthor https://nvtienanh.info
@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);
}
#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
}
Comments