使用PIC16F877A连接4×4矩阵键盘的教程-如何将矩阵键盘当作独立按键使用

键盘是广泛用于各种电子和嵌入式项目的输入设备。它们用于以数字和字母的形式获取输入,并将其输入系统以进行进一步处理。在本教程中,我们将使用PIC16F877A 连接 4×4 矩阵键盘。

为什么我们需要 4×4 键盘:

通常,我们使用微控制器单元的单个I / O引脚来读取数字信号,例如开关输入。在少数需要 9、12、16 个键进行输入的应用中,如果我们在微控制器端口中添加每个键,我们最终将使用 16 个 I/O 端口。这 16 个 I/O 端口不仅用于读取 I/O 信号,还可以用作外设连接,如 ADC 支持、I2C、SPI 连接也由这些 I/O 引脚支持。由于这些引脚与开关/键连接,因此我们不能将它们用作I / O端口。这完全没有意义。那么,如何减少引脚数呢?答案是,使用十六进制键盘或矩阵键盘;我们可以减少引脚数量,这些引脚数与4×4矩阵键相关联。它将使用 8 个引脚,其中 4 个成行连接,4 个以列连接,因此节省了微控制器的 8 个引脚。

4×4 矩阵键盘的工作原理:

使用PIC16F877A连接4x4矩阵键盘的教程-如何将矩阵键盘当作独立按键使用

在上图中,矩阵键盘模块显示在左侧。右侧显示了内部连接以及端口连接。如果我们看到端口有 8 个引脚,从左到右的前 4 个是 X1、X2、X3 和 X4 是行,从左到右的最后 4 个是Y1、Y2、Y3、Y4是四列。如果我们制作 4 行或 X 侧作为输出并使它们逻辑低或0,并将 4列作为输入并读取键,我们将在对应Y 得到 0时读取开关按下。

同样的事情也会发生在 nxn 矩阵中,其中 n是数字。可以是 3×3、6×6 等。

现在只要认为1 被按下了。然后1 位于 X1 行和 Y1 列。如果 X1 为 0,则 Y1 将为 0。以同样的方式,我们可以通过感应列 Y1、Y2、Y3 和 Y4 来感知 X1 行中的每个键。每个开关都会发生这种情况,我们将读取矩阵中开关的位置。

每个绿色圆圈都是开关,它们都以相同的方式连接在一起。

在本教程中,我们将使用以下规格连接键盘-

我们将使用内部上拉

我们将添加密钥去抖动选项

但是当开关没有被按下时,我们需要使Y1、Y2、Y3 和 Y4达到高或 1。否则,我们无法检测到按下开关时的逻辑变化。但是我们无法通过代码或程序来实现它,因为这些引脚用作输入,而不是输出。因此,我们将在微控制器中使用内部操作寄存器,并将这些引脚作为弱上拉使能模式运行。通过使用此功能,当它处于默认状态时,将有一个逻辑高使能模式。

此外,当我们按键时,开关触点会产生尖峰或噪音,因此会发生多次开关按下,这是意料之外的。因此,我们将首先检测开关按下,等待几毫秒,再次检查开关是否仍然按下,如果开关仍然按下,我们将接受开关按下最终,否则不会。这称为开关的去抖动。

我们将在代码中实现这一切,并在面包板上建立连接。

所需材料:

面包板

PC中的Pic-kit 3和开发环境,即MPLABX

电线和连接器

字符液晶屏 16×2

20兆赫晶体

2 个 33pF 陶瓷盘盖。

4.7k 电阻

10k 预设(可变电阻)

4×4 矩阵键盘

一个 5 V 适配器

电路图:

使用PIC16F877A连接4x4矩阵键盘的教程-如何将矩阵键盘当作独立按键使用

使用PIC16F877A连接4x4矩阵键盘的教程-如何将矩阵键盘当作独立按键使用

我们将连接相关引脚中的晶体和电阻器。此外,我们将通过PORTD 以 4 位模式连接LCD。我们将六角键盘或矩阵键盘连接到端口RB4。

编程说明:

最后给出了矩阵键盘与PIC微控制器接口的完整代码。代码简单易懂。键盘库只是在代码中要理解的东西。在这里,我们使用 keyboard.h 和 lcd.h 库来连接键盘和 16×2 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连接4×4矩阵键盘的教程-如何将矩阵键盘当作独立按键使用 https://www.yhzz.com.cn/a/6403.html

上一篇 2023-04-13 16:10:46
下一篇 2023-04-13

相关推荐

联系云恒

在线留言: 我要留言
客服热线:400-600-0310
工作时间:周一至周六,08:30-17:30,节假日休息。