鍵盤是廣泛用于各種電子和嵌入式項目的輸入設備。它們用于以數字和字母的形式獲取輸入,并將其輸入系統以進行進一步處理。在本教程中,我們將使用PIC16F877A 連接 4x4 矩陣鍵盤。
為什么我們需要 4x4 鍵盤:
通常,我們使用微控制器單元的單個I / O引腳來讀取數字信號,例如開關輸入。在少數需要 9、12、16 個鍵進行輸入的應用中,如果我們在微控制器端口中添加每個鍵,我們最終將使用 16 個 I/O 端口。這 16 個 I/O 端口不僅用于讀取 I/O 信號,還可以用作外設連接,如 ADC 支持、I2C、SPI 連接也由這些 I/O 引腳支持。由于這些引腳與開關/鍵連接,因此我們不能將它們用作I / O端口。這完全沒有意義。那么,如何減少引腳數呢?答案是,使用十六進制鍵盤或矩陣鍵盤;我們可以減少引腳數量,這些引腳數與4x4矩陣鍵相關聯。它將使用 8 個引腳,其中 4 個成行連接,4 個以列連接,因此節省了微控制器的 8 個引腳。
4x4 矩陣鍵盤的工作原理:
在上圖中,矩陣鍵盤模塊顯示在左側。右側顯示了內部連接以及端口連接。如果我們看到端口有 8 個引腳,從左到右的前 4 個是 X1、X2、X3 和 X4 是行,從左到右的最后 4 個是Y1、Y2、Y3、Y4是四列。如果我們制作 4 行或 X 側作為輸出并使它們邏輯低或0,并將 4列作為輸入并讀取鍵,我們將在對應Y 得到 0時讀取開關按下。
同樣的事情也會發生在 nxn 矩陣中,其中 n是數字。可以是 3x3、6x6 等。
現在只要認為1 被按下了。然后1 位于 X1 行和 Y1 列。如果 X1 為 0,則 Y1 將為 0。以同樣的方式,我們可以通過感應列 Y1、Y2、Y3 和 Y4 來感知 X1 行中的每個鍵。每個開關都會發生這種情況,我們將讀取矩陣中開關的位置。
每個綠色圓圈都是開關,它們都以相同的方式連接在一起。
在本教程中,我們將使用以下規格連接鍵盤-
我們將使用內部上拉
我們將添加密鑰去抖動選項
但是當開關沒有被按下時,我們需要使Y1、Y2、Y3 和 Y4達到高或 1。否則,我們無法檢測到按下開關時的邏輯變化。但是我們無法通過代碼或程序來實現它,因為這些引腳用作輸入,而不是輸出。因此,我們將在微控制器中使用內部操作寄存器,并將這些引腳作為弱上拉使能模式運行。通過使用此功能,當它處于默認狀態時,將有一個邏輯高使能模式。
此外,當我們按鍵時,開關觸點會產生尖峰或噪音,因此會發生多次開關按下,這是意料之外的。因此,我們將首先檢測開關按下,等待幾毫秒,再次檢查開關是否仍然按下,如果開關仍然按下,我們將接受開關按下最終,否則不會。這稱為開關的去抖動。
我們將在代碼中實現這一切,并在面包板上建立連接。
所需材料:
面包板
PC中的Pic-kit 3和開發環境,即MPLABX
電線和連接器
字符液晶屏 16x2
20兆赫晶體
2 個 33pF 陶瓷盤蓋。
4.7k 電阻
10k 預設(可變電阻)
4x4 矩陣鍵盤
一個 5 V 適配器
電路圖:
我們將連接相關引腳中的晶體和電阻器。此外,我們將通過PORTD 以 4 位模式連接LCD。我們將六角鍵盤或矩陣鍵盤連接到端口RB4。
編程說明:
最后給出了矩陣鍵盤與PIC微控制器接口的完整代碼。代碼簡單易懂。鍵盤庫只是在代碼中要理解的東西。在這里,我們使用 keyboard.h 和 lcd.h 庫來連接鍵盤和 16x2 LCD。讓我們看看里面發生了什么。
在keypad.h內部,我們將看到我們使用了默認寄存器庫的xc.h標頭,晶體頻率是為使用kepad.c文件中使用的延遲而定義的。我們在PORTRB寄存器上定義了鍵盤端口,并將各個引腳定義為行 (X)和列(Y)。
我們還使用了兩個函數,一個用于鍵盤初始化,它將端口重定向為輸出和輸入,另一個是開關按下掃描,它將在調用時返回開關按下狀態。
#include
#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
#define X_1 RB0
#define X_2 RB1
#define X_3 RB2
#define X_4 RB3
#define Y_1 RB4
#define Y_2 RB5
#define Y_3 RB6
#define Y_4 RB7
#define Keypad_PORT PORTB
#define Keypad_PORT_Direction TRISB
void InitKeypad(void);
char switch_press_scan(void);
在keypad.c中,我們將看到當鍵盤掃描儀函數未返回“n”時,下面的函數將返回按鍵。
char switch_press_scan(void) // Get key from user
{
char key = 'n'; // Assume no key pressed
while(key=='n') // Wait untill a key is pressed
key = keypad_scanner(); // Scan the keys again and again
return key; //when key pressed then return its value
}
下面是鍵盤讀取功能。在每個步驟中,我們將行 X1、X2、X3 和 X4 設為 0,并讀取 Y1、Y2、Y3 和 Y4 狀態。延遲用于去抖動效果,當仍然按下開關時,我們將返回與之關聯的值。當沒有按下開關時,我們將返回'n'。
char keypad_scanner(void)
{
X_1 = 0; X_2 = 1; X_3 = 1; X_4 = 1;
if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '1'; }
if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '2'; }
if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '3'; }
if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'A'; }
X_1 = 1; X_2 = 0; X_3 = 1; X_4 = 1;
if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '4'; }
if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '5'; }
if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '6'; }
if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'B'; }
X_1 = 1; X_2 = 1; X_3 = 0; X_4 = 1;
if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '7'; }
if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '8'; }
if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '9'; }
if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'C'; }
X_1 = 1; X_2 = 1; X_3 = 1; X_4 = 0;
if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '*'; }
if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '0'; }
if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '#'; }
if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'D'; }
return 'n';
}
我們還將在最后四個位上設置弱上拉,并將端口的方向設置為最后 4 個輸入和前 4 個作為輸出。 OPTION_REG &= 0x7F;用于在最后一個引腳上設置弱上拉模式。
void InitKeypad(void)
{
Keypad_PORT = 0x00; // Set Keypad port pin values zero
Keypad_PORT_Direction = 0xF0; // Last 4 pins input, First 4 pins output
OPTION_REG &= 0x7F;
}
在主PIC程序中(如下所示),我們首先設置了配置位,并包含了一些需要的庫。然后在無效的system_init功能中,我們初始化鍵盤和LCD。最后在主函數中,我們通過調用switch_press_scan()函數并將值返回給 lcd 來讀取鍵盤。
/*
* File: main.c
* Author: Sourav Gupta
* By:- circuitdigest.com
* Created on April 13, 2018, 2:26 PM
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#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/PGM pin has PGM function; low-voltage programming enabled)
#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)
#include
#include
#include
#include "supporing_cfile/lcd.h"
#include "supporing_cfile/Keypad.h"
/*
Hardware related definition
*/
#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
/*
Other Specific definition
*/
void system_init(void);
void main(void){
system_init();
char Key = 'n';
lcd_com(0x80);
lcd_puts("CircuitDigest");
lcd_com(0xC0);
while(1){
Key = switch_press_scan();
lcd_data(Key);
}
}
/*
* System Init
*/
void system_init(void){
TRISD = 0x00;
lcd_init(); // This will initialise the lcd
InitKeypad();
}
-
PIC16F877A
+關注
關注
2文章
43瀏覽量
21800 -
矩陣鍵盤
+關注
關注
7文章
206瀏覽量
31454
發布評論請先 登錄
相關推薦
評論