Thursday, March 24, 2016

BÀI 35 : GIAO TIẾP KEYPAD 4X4 PIC16F877A XC8

I. Keypad 4x4.
Keypad là một "thiết bị nhập" chứa các nút nhấn cho phép người dùng nhập các chữ số, chữ cái hoặc ký hiệu vào bộ điều khiển. Keypad không chứa tất cả bảng mã ASCII như keyboard và vì thế keypad thường được tìm thấy trong các thiết bị chuyên dụng. Các nút nhấn trên các máy tính điện tử cầm tay là một ví dụ về keypad. Số lượng nút nhấn của một keypad thay đổi phụ thuộc vào yêu cầu ứng dụng. Trong bài này tôi giới thiệu cách điều khiển của một loại keypad đơn giản, keypad 4x4.
Gọi là keypad 4x4 vì keypad này có 16 nút nhấn được bố trí dạng ma trận 4 hàng và 4 cột. Cách bố trí ma trận hàng và cột là cách chung mà các keypad sử dụng. Cũng giống như các ma trận LED, các nút nhấn cùng hàng và cùng cột được nối với nhau, vì thế với keypad 4x4 sẽ có tổng cộng 8 ngõ ra (4 hàng và 4 cột). Mô hình Keypad 4x4 được thể hiện trong hình 1.
keypad 4x4
Hình 1.
Hình ở trên là hình mô phỏng trên phần mềm protues mình chụp lại để các bạn hình dung nó như thế nào thôi ! Còn thực chất thì nó được cấu tạo như sau :
keypad 4x4
Có rất nhiều cách khác nhau để làm bài này các bạn thích làm theo cánh bào thì làm. Như trong hình trên thì chúng ta sẽ thấy các chân C1 - C4 sẽ nối với mức 0 từ chân Vi Điều Khiển, và các chân từ R1- R4 sẽ được nối với trở và nối vào mức 1 của Vi Điều khiển ! Và chúng ta sẽ quét theo hàng và cột giống như 1 mảng vậy !
- Đây là ảnh mô phỏng protues.

giao tiếp với keypad 4x4 pic16f877a

- Đây là code chương trình.
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
#define RS RD1
#define EN RD0
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include <xc.h>
#include "lcd.h"
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
//#define set_port_kbd PORTB // Change if port is different
// Define pins
// Define pins
#define RowA RB0
#define RowB RB1
#define RowC RB2
#define RowD RB3
#define C1 RB4
#define C2 RB5
#define C3 RB6
#define C4 RB7

#define Keypad_PORT PORTB
#define Keypad_PORT_Dir TRISB
void InitKeypad(void);
char GetKey(void);
void main(void) {
     TRISD = 0x00;
     PORTD   = 0;
     Lcd_Init();
     Lcd_Set_Cursor(1,1);
     Lcd_Write_String("By LAM 3 NGON");
     Lcd_Set_Cursor(2,1);
     Lcd_Write_String("KeyPad Control...");
     __delay_ms(1000);
     Lcd_Clear();
     Lcd_Set_Cursor(1,1);                  
     Lcd_Write_String("Enter Key");
     Lcd_Set_Cursor(2,1);
     Lcd_Write_String("");
char Key = 'n'; // Variable to store pressed key value
InitKeypad(); // Initialize Keypad pins
while(1)
{
Key = GetKey(); // Get pressed key from keypad
Lcd_Write_Char(Key); // Update LCD with current key value
}
}
// Function name: InitKeypad
void InitKeypad(void)
{
Keypad_PORT    = 0x00; // Set Keypad port pin values zero
Keypad_PORT_Dir = 0xF0; // Last 4 pins input, First 4 pins output

// Enable weak internal pull up on input pins
OPTION_REG &= 0x7F;
}



// Function name: READ_SWITCHES
// Scan all the keypad keys to detect any pressed key.
char READ_SWITCHES(void)
{
RowA = 0; RowB = 1; RowC = 1; RowD = 1; //Test Row A

if (C1 == 0) { __delay_ms(250); while (C1==0); return '7'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '8'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '9'; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return '/'; }

RowA = 1; RowB = 0; RowC = 1; RowD = 1; //Test Row B

if (C1 == 0) { __delay_ms(250); while (C1==0); return '4'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '5'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '6'; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return 'x'; }

RowA = 1; RowB = 1; RowC = 0; RowD = 1; //Test Row C

if (C1 == 0) { __delay_ms(250); while (C1==0); return '1'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '2'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '3'; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return '-'; }

RowA = 1; RowB = 1; RowC = 1; RowD = 0; //Test Row D

if (C1 == 0) { __delay_ms(250); while (C1==0); return 'C'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '0'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '='; }
if (C4 == 0) { __delay_ms(250); while (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

}
- Link download project Click here

9 comments:

  1. sao file không tải được nữa thế các bác

    ReplyDelete
  2. File bị mất rồi bạn chịu khó copy và vẽ lại file mô phỏng nha !

    ReplyDelete
    Replies
    1. lỗi 128 line 34 A#DEVICE required before this line giúp e sữa với a!

      Delete
  3. cho em hỏi thư viện lcd.h bên trong code như nào đó ạ

    ReplyDelete
  4. Bạn xem lại các bài đăng trước thử nhé, xem có không nhé.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. a ơi em muốn đổi C1 C2 C3 C4 sang portA hoặc portC thì cần làm như nào ạ,em cảm ơn ạ duongbaxxx@gmail.com

    ReplyDelete