知不足而奋进 望远山而前行
目录
前言
矩阵键盘作为一种常见的数字输入设备,在各类电子产品和嵌入式系统中广泛应用。通过多行多列的按键组成矩阵结构,实现了在有限的引脚数量下输入大量信息的功能。本文将深入探讨矩阵键盘的原理、基本结构和按键扫描方法,并介绍如何通过编程实现矩阵键盘的功能。读者将从中了解矩阵键盘的工作原理,掌握按键状态检测的方法,同时学会如何通过编程实现矩阵键盘的应用,为相关电子项目的设计与开发提供帮助。
学习目标
- 了解矩阵键盘的原理和基本结构
- 学会矩阵键盘的按键扫描方法
- 学会矩阵键盘的编程实现
学习内容
矩阵按键
矩阵键盘是一种常见的数字输入设备,由多行多列的按键组成。每个按键都有一个唯一的行列坐标,通过行列坐标可以确定按键的编号,从而实现对数字或字母的输入。
原理图
矩阵键盘的基本结构包括按键、行引脚和列引脚。按键一般是机械按键或触摸按键,行引脚和列引脚分别与矩阵键盘的行和列相连,用于检测按键的输入状态。
按键状态检测
单个按键状态检测
- 输出端的电平
- 输入端的状态
- 按键抬起
通过按键抬起时的状态,我们分析输入端的电平信号,来确定抬起时输入端的默认电平状态。
通过按键按下时的状态,我们分析输入端的电平信号,来确定按下时输入端的默认电平状态。
通过分析确认,默认输出端和输入端都是高电平;
- 当输出端输出低电平时,输入端为高电平 ,则开关为抬起状态;
- 当输出端输出低电平时,输入端为低电平 ,则开关为按下状态;
单行按键状态检测
通过逐一检测输入端的状态,来判断按键是否按下。
多行按键状态检测
首先,将第一行输出低电平 ,其余行设置为高电平。目的是为了只测试第一行的按键状态。
然后,将第二行输出低电平 ,其余行设置为高电平。目的是为了只测试第二行的按键状态。
接着,将第三行输出低电平 ,其余行设置为高电平。目的是为了只测试第三行的按键状态。
最后,将第四行输出低电平 ,其余行设置为高电平。目的是为了只测试第四行的按键状态。
状态记录
通过自定义状态来记录按键状态
// 记录16个按键状态,0为按下,1为抬起
u16 key_state = 0xFFFF;
......
void scan() {
// 初始都是 高电平
ROW_COL_RESET();
NOP1();
// ROW1
// 给 row1 低电平,读取COL1的值
ROW1 = 0;
NOP1();
// 当前是UP,当之前是DOWN,则为UP
// 当前是DOWN,当之前是UP,则为DOWN
if(COL1 != (key_state & 0x01) >> 0) {
if(COL1) {
// 修改当前状态为UP
key_state |= 0x01;
printf("K1 Up\r\n");
} else {
// 修改当前状态为DOWN
key_state &= ~0x01;
printf("K1 Down\r\n");
}
}
......
}
状态优化
通过define
优化一些数值的操作,方便在后续看代码时方便理解,提高代码的阅读性。
// 记录16个按键状态,0为按下,1为抬起
u16 key_state = 0xFFFF;
#define KEY_UP 1
#define KEY_DOWN 0
// 第n个按键的状态
#define KEY_STATE(n) ((key_state & (1 << n)) >> n)
#define SET_KEY_UP(n) (key_state |= (1 << n))
#define SET_KEY_DOWN(n) (key_state &= ~(1 << n))
#define ROW_COL_RESET() {ROW1=1,ROW2=1,ROW3=1,ROW4=1;COL1=1,COL2=1,COL3=1,COL4=1;}
......
void scan() {
// 初始都是 高电平
ROW_COL_RESET();
NOP1();
// ROW1
// 给 row1 低电平,读取COL1的值
ROW1 = 0;
NOP1();
// 当前是UP,当之前是DOWN,则为UP
// 当前是DOWN,当之前是UP,则为DOWN
if(COL1 != KEY_STATE(0)) {
if(COL1) {
// 修改当前状态为UP
SET_KEY_UP(0);
printf("K1 Up\r\n");
} else {
// 修改当前状态为DOWN
SET_KEY_DOWN(0);
printf("K1 Down\r\n");
}
}
......
}
循环优化
操作的按键众多,通过循环的方式来操控每一个按键,减少代码量,方便维护。
#define ROW 4
#define COL 4
// 记录16个按键状态,0为按下,1为抬起
u16 key_state = 0xFFFF;
#define KEY_UP 1
#define KEY_DOWN 0
// 第n个按键的状态
#define KEY_STATE(r, c) ((key_state & (1 << (r * ROW + c))) >> (r * ROW + c))
#define SET_KEY_UP(r, c) (key_state |= (1 << (r * ROW + c)))
#define SET_KEY_DOWN(r, c) (key_state &= ~(1 << (r * ROW + c)))
#define ROW_COL_RESET() {ROW1=1,ROW2=1,ROW3=1,ROW4=1;COL1=1,COL2=1,COL3=1,COL4=1;}
void scan() {
u8 i, j;
for(i = 0; i < ROW; i++) {
// 初始都是 高电平
ROW_COL_RESET();
NOP1();
ROW_ON(i);
for(j = 0; j < COL; j++) {
// 当前是UP,当之前是DOWN,则为UP
// 当前是DOWN,当之前是UP,则为DOWN
if(COL_STATE(j) != KEY_STATE(i, j)) {
if(COL_STATE(j)) {
// 修改当前状态为UP
SET_KEY_UP(i, j);
printf("(%d, %d) Up\r\n", (int)i, (int)j);
} else {
// 修改当前状态为DOWN
SET_KEY_DOWN(i, j);
printf("(%d, %d) Down\r\n", (int)i, (int)j);
}
}
}
}
}
总结
通过本文的学习,我们深入了解了矩阵键盘的原理和基本结构,掌握了矩阵键盘的按键扫描方法和编程实现技巧。矩阵键盘通过行列的组合排列,实现了多个按键共用少量引脚的设计,同时提供了灵活输入和高效交互的功能。通过逐一检测按键的状态,我们可以准确判断按键的按下和抬起状态,从而实现对按键输入的有效监控和响应。
通过优化状态记录和循环操作,我们能够简化代码结构,提高代码的可读性和维护性。通过合理的编程实现,可以更高效地处理矩阵键盘的输入信号,实现各种个性化的功能和交互效果。掌握矩阵键盘的原理和编程方法,将有助于读者在实际项目中应用和拓展矩阵键盘的功能,为电子产品的设计与开发提供技术支持。