Đă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
}

Video demo