4×4按键模块有8个接脚,分成列、行两组,可以接在 的任意8个接脚,笔者将它接在数位6~13脚:
为了简化接线,可以使用“长脚型”排针,将其中两个脚用尖嘴钳稍微折弯,即可插入 的排母:
排针上头的黑色塑料,可以用蛮力让它移到中间的位置,以便衔接两边的排母:
4×4薄膜键盘的 按键侦测程序
撰写 按键侦测程序,最简单也是最好的方式,就是采用既有的程序库。本单元将示范使用 AA程序库,把侦测到的按键字符显示在序列端口监控视窗。请按此下载 AA程序库(原始出处在这篇 AA介绍文),解压缩之后,置入 的libraries路径:
底下的程序,修改自 AA程序库的“Hello AA”示例,使用此程序库,我们的代码需要定义按键模块的行(col)、列(row)数、连接 的脚位以及按键所代表的字符
#include// 引用 AA程式库
#define KEY_ROWS 4 // 按键模组的列数
#define KEY_COLS 4 // 按键模组的行数
// 依照行、列排列的按键字符(二维阵列)
char keymap[KEY_ROWS][KEY_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte colPins[KEY_COLS] = {9, 8, 7, 6}; // 按键模组,行1~4接脚。
byte rowPins[KEY_ROWS] = {13, 12, 11, 10}; // 按键模组,列1~4接脚。
// 初始化 AA物件
// 语法: AA(makeKeymap(按键字符的二维阵列), 模组列接脚, 模组行接脚, 模组列数, 模组行数)
AA my AA = AA(makeKeymap(keymap), rowPins, colPins, KEY_ROWS, KEY_COLS);
void setup(){
Serial.begin(9600);
}
void loop(){
// 透过 AA物件的getKey()方法读取按键的字符
char key = my AA.getKey();
if (key){ // 若有按键被按下…
Serial.println(key); // 显示按键的字符
}
}
编译并上传代码,再开启“序列监控视窗”,按下薄膜键盘的任何按键,该字符将显示在序列端口监控视窗。
按键侦测与扫描原理
为了方便解说,笔者把4×4按键简化成3×1,像下图这样串连三个开关,连接到同一个微控制器的输入脚。此外,因为要简化开关电路,所以要启用微控器内部的上拉电阻:
假设开关的“行1”~“行3”输入端全都输入高电位,无论开关是否被按下, 将接收到高电位(1)。为了检测到其中按键被按下,程序必须依序将“行1”~“行3”脚位设定成低电位。
轮到“行2”脚输入低电位,此时,微控器的输入脚也将接收到低电位(0),由此可知连接“行2”的“开关B”被按下了
轮到“行3”脚输入低电位,由于“开关C”未被按下,因此微控器的输入脚接收到高电位(1)。
到此,侦测按键的程序必须再次回到“行1”,输入低电位…如此反复循环扫描,才能持续侦测到某个按键是否被按下。实际的程序需要运用双重循环,才能分批扫描每一列:
双重循环的练习,请参阅《超图解 互动设计入门》第8章“LED矩阵动画与多维数组程序设计”一节,8-28页
自行撰写扫描按键的程序
根据以上说明,自行撰写扫描按键的代码:
const byte colPins[4] = {9, 8, 7, 6}; // 设定“行”脚位
const byte rowPins[4] = {13, 12, 11, 10}; // 设定“列”脚位
const char keymap[4][4] = { // 设定按键的“行、列”代表值
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte i, j; // 暂存循环的索引数字
byte scanVal; // 暂存扫描到的按键值
void setup(){
Serial.begin(9600);
for (i = 0; i < = 3; i++) {
pinMode(rowPins[i], INPUT);
pinMode(colPins[i], OUTPUT);
digitalWrite(colPins[i], HIGH);
digitalWrite(rowPins[i], HIGH);
}
}
void loop() {
for (i = 0; i <= 3; i++) {
for (j = 0; j <= 3; j++) {
digitalWrite(colPins[j], LOW);
scanVal = digitalRead(rowPins[i]);
if (scanVal == LOW) { // 如果输入值是“低电位”…
Serial.println(keymap[i][j]); // 输出按键代表的字符
delay(200); // 扫描按键的间隔时间
digitalWrite(colPins[j], HIGH);
break; // 跳出循环
}
digitalWrite(colPins[j], HIGH);
}
}
}
AA程序库的运作方式大致上面的程序相同,主要是多了消除弹跳(debounce)的程序(相关说明请参阅第四章“解决开关信号的弹跳问题”一节,4-15页),而且按键扫描的间隔时间是透过比对时间差,而非使用delay。上面的程序用于帮助理解扫描按键的原理,在实际项目制作上,请使用 AA程序库。