- Đăng vào
Lập trình bàn phím 4x4 với vi điều khiển PIC16F877
Bài viết này sẽ hướng dẫn các bạn quét bàn phím (keypad) 4x4 và hiển thị ký tự được ấn lên LCD 16x2, 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
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);
}
}
#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://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);
}
#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
}