当设计中按键较多,但单片机I/O资源有限时,使用矩阵键盘是一个不错的选择。当按键较少时,矩阵键盘没有明显优势。比如33矩阵键盘占用6个I/O口,只支持9个键;但当按键较多时,矩阵键盘的优势就凸显出来了。比如一个55的矩阵键盘,占用10个I/O口,可以支持25个键;矩阵键盘的硬件设计非常简单,如图1所示。以55矩阵键盘为例,有5条蓝色的行线和5条绿色的列线(加上拉电阻),矩阵键盘是用按键代替行和列的相交节点形成的,其中二极管处的红色连接线可以用来检测按键是否被按下,或者作为中断信号使用(可能不需要,使用时不会有影响,本文不涉及)。
图1:矩阵键盘
图2为单片机STM32F103CBT6的外围电路,彩色I/O口为矩阵键盘的行线PA1~PA5(蓝色)和列线PA6~PA10(绿色)。为了编程方便,矩阵键盘最好选择同一组的I/O口。
图2:单片机外围电路
硬件设计是上面的部分,接下来说明程序部分。
键盘的扫描方式有很多种,其中行列反转扫描非常流行,不仅简单而且效率高,掌握这种方式就足够了。
行列反转扫描的逻辑:
所有行线输出为0(行线PA1~PA5配置为推挽输出,列线PA6~PA10配置为上拉输入)
读入列线值。
输出列线值(行线PA1~PA5配置为上拉输入,列线PA6~PA10配置为推挽输出)
读入行值。
组合的行线和列线值
对于STM32单片机,直接操作寄存器会更简单,不需要另外配置I/O。所有代码如图3所示,可以作为一个模块使用。
图3:矩阵键盘的行列反转扫描
下面的代码与图3中的代码完全相同(便于浏览和复制)
/*-5 *-矩阵键盘扫描函数,返回扫描键值(行列扫描)/u16key。u16 key _ value=0xFFFFGPIOA-CRL=0x 88333334;GPIOA-CRH=0x 44444888;GPIOA-ODR=GPIOA-IDR0x ffc 1;cord _ l=GPIOA-IDR0x 07 c 0;if(cord_l!=0x07c 0){ delay _ ms(10);if(cord_l!=0x07c 0){ cord _ l=GPIOA-IDR0x07c 0;GPIOA-CRL=0x 33888884;GPIOA-CRH=0x 44444333;GPIOA-ODR=cord _ l |0x f83 f;delay _ us(1);cord _ h=GPIOA-IDR0x 003 e;cord _ h=1;cord _ l=1;key _ value=(cord _ l cord _ h)0x ffff;return(key _ value);} } return(0x ffff);}下面的代码是端口配置寄存器的操作。PA组I/O有16个管脚:PA0 ~ PA15;3代表推挽输出,4代表浮动输入,8代表上拉输入;
GPIOA-CRL=0x 88333334;//低8位配置GPIOA-CRH=0x 44444888;//下面代码中的高8位配置,GPIOA-ODR是端口输出数据寄存器,用于写操作;GPIOA-IDR是端口输入数据寄存器,用于读操作;
0xFFC1的二进制:1111 1111 1100 0001,表示将0设置为PA1~PA5。
0x07C0: 0000 0111 1100 0000的二进制数,表示从PA6至PA10读取值。
GPIOA-ODR=GPIOA-IDR0x ffc 1;//所有行和线输出为0 cord _ l=GPIOA-IDR0x 07 c 0;//列反转后读入列行值的原理和上面一模一样,所以我赢了这里就不解释了。
最后,让让我们来谈谈组合行和列行的值。如果按下S1键,获得的二进制值是(注意粗体字)。
0000 0000 0011 1100
cord_l:0000 0111 1000 0000
Cord_h=1表示向右移位1位,得到:
0000 0000 0001 1110
Cord_l=1表示向右移位1位,得到:
0000 0011 1100 0000
组合码(键值):key _ value=0000011101 1110,即0x 03 de;最后,函数返回key_value的值,作为判断S1的键值。
右移的原因是矩阵键盘不使用PA0,所以得到的键值左移1位。其实不需要右移,只是得到的组合码不一样。右移是为了计算方便。
键盘的键值定义如下:
#定义S10x 03 de #定义S20x 03 be #定义S30x 037 e #定义S40x 02 Fe #定义S50x01FE #定义S60x03DD #定义S70x03BD #定义S80x037D#定义S90x02FD #定义S100x01FD #定义S110x03DB #定义S120x03BB #定义S130x037B #定义S140x02FB #定义S160x03D7#定义es 170x 03 b #定义S180x0377 #定义S190x02f7 #定义S19
行列反转扫描的思想是在行线作为输出时读出列线的值;然后依次当列线作为输出时,读取行线的值,最后将两个值组合得到key的键值;
参与计算的十六进制数必须与同一组端口中的行线或列线位置相匹配。比如二进制数0xFFC1: 1111 1111 1100 0001表示PA1~PA5要置0。
审计郭婷
标签:键盘矩阵GPIOA