一 电路原理
矩阵键盘电路原理图如下:
矩阵键盘电路图
矩阵键盘相比于独立按键的优势在于:使用同样的单片机端口,矩阵键盘可以驱动更多的按键数量。
二 代码示例
const int numRows = 4; // 定义4行
const int numCols = 4; // 定义4列
const int debounceTime = 20; //去抖动时间长度
const char keymap[numRows][numCols] = { //键值,可以按需要更改
{'1', '2', '3', '+'},
{'4', '5', '6', '-'},
{'7', '8', '9', 'X'},
{'*', '0', '#', '@'}
};
const int rowPins[numRows] = {7, 6, 5, 4}; // 设置硬件对应的引脚
const int colPins[numCols] = {11, 10, 9, 8};
// 初始化功能
void setup() {
Serial.begin(9600);
//将行列设为对应输入输出模式,全设为高电平。
for (int row = 0; row < numRows; row++) {
pinMode(rowPins[row], INPUT);
digitalWrite(rowPins[row], HIGH);`
}
for (int column = 0; column < numCols; column++) {
pinMode(colPins[column], OUTPUT);
digitalWrite(colPins[column], HIGH);
}
}
// 主循环
void loop() {
// 添加其他的程序,循环运行
char key = getkey();
if (key != 0) {
Serial.print("Got key: "); // 串口打印键值
Serial.println(key);
}
}
// 读取键值程序
char getkey() {
char key = 0;
for (int column = 0; column < numCols; column++) {
digitalWrite(colPins[column], LOW);
for (int row = 0; row < numRows; row++) {
if (digitalRead(rowPins[row]) == LOW) { // 是否有按键按下
delay(debounceTime);
while (digitalRead(rowPins[row]) == LOW); // 等待按键释放
key = keymap[row][column];
}
}
digitalWrite(colPins[column], HIGH); // 关闭当前列
}
return key;
}
2.1 接线方式:
const int rowPins[numRows] = {7, 6, 5, 4}; // 设置硬件对应的引脚
const int colPins[numCols] = {11, 10, 9, 8};
根据代码进行对应引脚的接线,可自行根据设计确定。
2.2 函数解释
读取键值的函数实现以下步骤
1、4个行线全部设为输出,并置高电平;
2、4个列线全部设为输入,并置高电平(内部上拉作用);
第一行线拉低(LOW)检测4根列线是否有低电平出现?如果有,证明有按键按下去抖,再次确认,直到按键释放,读取4个列线值,通过矩阵数组确定按键键值,如果没有则继续下一步。释放改行线(置高HIGHT)。
第二行线拉低(LOW)检测4根列线是否有低电平出现?如果有,证明有按键按下:去抖,再次确认,直到按键释放,读取4个列线值,通过矩阵数组确定按键键值,如果没有则继续下一步。释放改行线(置高HIGHT)。
第三行线拉低(LOW)检测4根列线是否有低电平出现?如果有,证明有按键按下,去抖,再次确认,直到按键释放,读取4个列线值,通过矩阵数组确定按键键值,如果没有则继续下一步。释放改行线(置高HIGHT)。
第四行线拉低(LOW)检测4根列线是否有低电平出现?如果有,证明有按键按下去抖,再次确认,直到按键释放,读取4个列线值,通过矩阵数组确定按键键值,如果没有则继续下一步。释放改行线(置高HIGHT)。
三 可能遇到的问题
1 需要判断矩阵键盘接口左右两边分别控制的是行还是列,这里可以通过使用代码寻找规律,再自行更改引脚接入顺序。
2 对单片机写入程序时,需要先拔掉矩阵键盘再写入。