背景介绍:
4*4矩阵键盘 8 根线能获取 16 个键的状态,在需要多个按键的场合特别适用。
Sugar 因授课需要在网上查了不少讲解矩阵键盘的资料,觉得可以再努努力让这个知识更易懂一点。
下面就来看看 Sugar 怎么努力的吧。
矩阵键盘是什么
矩阵键盘就是按一定规律连在一起的一堆开关。
Sugar 从深圳优信电子买到的矩阵键盘长成这样的(Sugar 买过不少散电子元件,优信从未出过错,所以在这里提个名)。
这一堆开关的连接情况是这样的:
矩阵键盘怎么用
矩阵键盘需要接到单片机上用。
一、怎么连线
网上能找到的是接到 STM32、Arduino 和 C51 单片机上的。Sugar 今天给出个不同的:接到 ESP8266 物联网模块上用。接法如下图:
实物连接如下图:
注意:GPIO16 在 ESP8266 内部没有上拉电阻,所以要外接上拉电阻,上图中 Sugar 接了一个 10k 的色环电阻当作 GPIO16 的上拉电阻。其余接口(GPIO12、GPIO13、GPIO14)可配置内部上拉,配置方式是(以 Arduino 开发为例):
pinMode(12, INPUT_PULLUP);pinMode(13, INPUT_PULLUP);pinMode(14, INPUT_PULLUP);123
二、怎么使用
1、默认状态下,让输出口统一输出低电平,如下图:
不难看出行引脚(1、2、3、4 引脚)都是低电平,因为没有按键按下,所以列引脚(5、6、7、8 引脚)被上拉都是高电平。这样在读取 GPIO12、GPIO13、GPIO14、GPIO16 的时候都会读到高电平。
2、当有按键被按住的时候(例如按下 K7)如下:
聪明的你一定会发现,按矩阵键盘的连接方式,不论按下 K3、K7、K11 或 K15 都会导致 GPIO14 读到低电平。也就是说在 GPIO14 读到低电平时并不能确定是哪一行的按键被按住了,所以需要进一步操作来确认:究竟是哪一行的按键被按住了。
3、逐行扫描确定按键的方法是:输出端(GPIO4、GPIO0、GPIO2 和 GPIO15)依次输出低电平,每次输出后都去读一下输入端,直到输入端读到低电平为止。系列图示如下:
我们看到在逐行扫描过程中,只有当扫描到被按住的键所在行列的时候,输入端才会读到低电平。那么我们就可以通过记录行号和列号来确定是哪一个键被按住了。
把上面的图片连起来,整体的过程是这样的:
怎么编程
Sugar 在 VSCode 下使用 platformio 写代码,用的是 Arduino 库。
为了避免像很多网上的程序那样使用过多的移位操作,Sugar 使用 union struct 的方式来标记行号与列号,如下:
typedef union{ struct{ uint8_t r1 : 1; uint8_t r2 : 1; uint8_t r3 : 1; uint8_t r4 : 1; uint8_t c1 : 1; uint8_t c2 : 1; uint8_t c3 : 1; uint8_t c4 : 1; }; uint8_t value;}keyboard;12345678910111213
这样我们就可以写一个统一的读取列装态的函数,如下:
void read_column(){ key.c1 = digitalRead(13); key.c2 = digitalRead(12); key.c3 = digitalRead(14); key.c4 = digitalRead(16);}1234567
对于输出口,Sugar 封装一个 write_row() 函数来记录 key.r1~key.r4 的状态,如下:
void write_row(uint8_t pin, uint8_t value){ digitalWrite(pin, value); switch(pin){ case 0:{ key.r3 = value; //Serial.printf("r3: %drn", key.r3); break; } case 2:{ key.r2 = value; //Serial.printf("r2: %drn", key.r2); break; } case 4:{ key.r4 = value; //Serial.printf("r4: %drn", key.r4); break; } case 15:{ key.r1 = value; //Serial.printf("r1: %drn", key.r1); break; } }}1234567891011121314151617181920212223242526
至此,union struct 的所有位都有相应的取值方法了,现在可以按上面说过的矩阵键盘使用方法来完成键盘扫描函数 key_scan() 如下:
void key_scan(){ write_row(15, 0); write_row(2, 0); write_row(0, 0); write_row(4, 0); read_column(); if((key.value & 0xF0) != 0xF0){ delay(10); if((key.value & 0xF0) != 0xF0){ stage = GET_ROW; } } else { key_value = NONE; } if(stage == GET_ROW){ for(uint8_t i=0; i<4; i++){ switch(i){ case 0:{ write_row(15, 0); write_row(2, 1); write_row(0, 1); write_row(4, 1); read_column(); break; } case 1:{ write_row(15, 1); write_row(2, 0); write_row(0, 1); write_row(4, 1); read_column(); break; } case 2:{ write_row(15, 1); write_row(2, 1); write_row(0, 0); write_row(4, 1); read_column(); break; } case 3:{ write_row(15, 1); write_row(2, 1); write_row(0, 1); write_row(4, 0); read_column(); break; } } get_key_val(); if(key_value != NONE){ break; } } stage = DONE; }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
上面只给出了关键代码,像键值获取函数 get_key_val() 和状态机的写法都没有展开来是因为:展开全部代码太占篇幅了。想要全部代码的读者可以在“关于我”页面最下方加 Sugar 为好友索取。
为了证实 Sugar 上文所述真实有效,这里放一个 10 秒钟的矩阵键盘控制 ESP8266 Wifi 小车的视频:
wifi car
PS
相对于 Sugar 的麦轮车,这个 ESP8266 Wifi 小车既便宜又简单,是初入门创客动手实践的上上之选。小车是用 Mixly 的 Scratch 图形化编程写的程序,这里用到了来自 CSDN 的 Mixly ESP8266 Wifi 开发包,链接如下:
https://download.csdn.net/download/qq_27163873/10654977
这个 Mixly 包因缺少一个积木块程序而无法完成双 ESP8266 之间的互联(一个 AP Server,另一个 STA Client 互联),所以 Sugar 在其基础上做了进一步完善,使之能够不依赖路由器完成双 ESP8266 通信,如下:
想要整套完成程序的读者可以加 Sugar 为好友索取(不支持伸手党,所以不是免费的,但不标价,随意给个打赏就好)。
背景介绍:
4*4矩阵键盘 8 根线能获取 16 个键的状态,在需要多个按键的场合特别适用。
Sugar 因授课需要在网上查了不少讲解矩阵键盘的资料,觉得可以再努努力让这个知识更易懂一点。
下面就来看看 Sugar 怎么努力的吧。
矩阵键盘是什么
矩阵键盘就是按一定规律连在一起的一堆开关。
Sugar 从深圳优信电子买到的矩阵键盘长成这样的(Sugar 买过不少散电子元件,优信从未出过错,所以在这里提个名)。
这一堆开关的连接情况是这样的:
矩阵键盘怎么用
矩阵键盘需要接到单片机上用。
一、怎么连线
网上能找到的是接到 STM32、Arduino 和 C51 单片机上的。Sugar 今天给出个不同的:接到 ESP8266 物联网模块上用。接法如下图:
实物连接如下图:
注意:GPIO16 在 ESP8266 内部没有上拉电阻,所以要外接上拉电阻,上图中 Sugar 接了一个 10k 的色环电阻当作 GPIO16 的上拉电阻。其余接口(GPIO12、GPIO13、GPIO14)可配置内部上拉,配置方式是(以 Arduino 开发为例):
pinMode(12, INPUT_PULLUP);pinMode(13, INPUT_PULLUP);pinMode(14, INPUT_PULLUP);123
二、怎么使用
1、默认状态下,让输出口统一输出低电平,如下图:
不难看出行引脚(1、2、3、4 引脚)都是低电平,因为没有按键按下,所以列引脚(5、6、7、8 引脚)被上拉都是高电平。这样在读取 GPIO12、GPIO13、GPIO14、GPIO16 的时候都会读到高电平。
2、当有按键被按住的时候(例如按下 K7)如下:
聪明的你一定会发现,按矩阵键盘的连接方式,不论按下 K3、K7、K11 或 K15 都会导致 GPIO14 读到低电平。也就是说在 GPIO14 读到低电平时并不能确定是哪一行的按键被按住了,所以需要进一步操作来确认:究竟是哪一行的按键被按住了。
3、逐行扫描确定按键的方法是:输出端(GPIO4、GPIO0、GPIO2 和 GPIO15)依次输出低电平,每次输出后都去读一下输入端,直到输入端读到低电平为止。系列图示如下:
我们看到在逐行扫描过程中,只有当扫描到被按住的键所在行列的时候,输入端才会读到低电平。那么我们就可以通过记录行号和列号来确定是哪一个键被按住了。
把上面的图片连起来,整体的过程是这样的:
怎么编程
Sugar 在 VSCode 下使用 platformio 写代码,用的是 Arduino 库。
为了避免像很多网上的程序那样使用过多的移位操作,Sugar 使用 union struct 的方式来标记行号与列号,如下:
typedef union{ struct{ uint8_t r1 : 1; uint8_t r2 : 1; uint8_t r3 : 1; uint8_t r4 : 1; uint8_t c1 : 1; uint8_t c2 : 1; uint8_t c3 : 1; uint8_t c4 : 1; }; uint8_t value;}keyboard;12345678910111213
这样我们就可以写一个统一的读取列装态的函数,如下:
void read_column(){ key.c1 = digitalRead(13); key.c2 = digitalRead(12); key.c3 = digitalRead(14); key.c4 = digitalRead(16);}1234567
对于输出口,Sugar 封装一个 write_row() 函数来记录 key.r1~key.r4 的状态,如下:
void write_row(uint8_t pin, uint8_t value){ digitalWrite(pin, value); switch(pin){ case 0:{ key.r3 = value; //Serial.printf("r3: %drn", key.r3); break; } case 2:{ key.r2 = value; //Serial.printf("r2: %drn", key.r2); break; } case 4:{ key.r4 = value; //Serial.printf("r4: %drn", key.r4); break; } case 15:{ key.r1 = value; //Serial.printf("r1: %drn", key.r1); break; } }}1234567891011121314151617181920212223242526
至此,union struct 的所有位都有相应的取值方法了,现在可以按上面说过的矩阵键盘使用方法来完成键盘扫描函数 key_scan() 如下:
void key_scan(){ write_row(15, 0); write_row(2, 0); write_row(0, 0); write_row(4, 0); read_column(); if((key.value & 0xF0) != 0xF0){ delay(10); if((key.value & 0xF0) != 0xF0){ stage = GET_ROW; } } else { key_value = NONE; } if(stage == GET_ROW){ for(uint8_t i=0; i<4; i++){ switch(i){ case 0:{ write_row(15, 0); write_row(2, 1); write_row(0, 1); write_row(4, 1); read_column(); break; } case 1:{ write_row(15, 1); write_row(2, 0); write_row(0, 1); write_row(4, 1); read_column(); break; } case 2:{ write_row(15, 1); write_row(2, 1); write_row(0, 0); write_row(4, 1); read_column(); break; } case 3:{ write_row(15, 1); write_row(2, 1); write_row(0, 1); write_row(4, 0); read_column(); break; } } get_key_val(); if(key_value != NONE){ break; } } stage = DONE; }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
上面只给出了关键代码,像键值获取函数 get_key_val() 和状态机的写法都没有展开来是因为:展开全部代码太占篇幅了。想要全部代码的读者可以在“关于我”页面最下方加 Sugar 为好友索取。
为了证实 Sugar 上文所述真实有效,这里放一个 10 秒钟的矩阵键盘控制 ESP8266 Wifi 小车的视频:
wifi car
PS
相对于 Sugar 的麦轮车,这个 ESP8266 Wifi 小车既便宜又简单,是初入门创客动手实践的上上之选。小车是用 Mixly 的 Scratch 图形化编程写的程序,这里用到了来自 CSDN 的 Mixly ESP8266 Wifi 开发包,链接如下:
https://download.csdn.net/download/qq_27163873/10654977
这个 Mixly 包因缺少一个积木块程序而无法完成双 ESP8266 之间的互联(一个 AP Server,另一个 STA Client 互联),所以 Sugar 在其基础上做了进一步完善,使之能够不依赖路由器完成双 ESP8266 通信,如下:
想要整套完成程序的读者可以加 Sugar 为好友索取(不支持伸手党,所以不是免费的,但不标价,随意给个打赏就好)。
举报