设计中在遇到按键较多,但是单片机i/o资源有限时,采用矩阵键盘是一种很好的选择方案。在按键较少时,矩阵键盘没有明显的优势,比如3×3矩阵键盘占用i/o口6个,只支持9个按键;但是,按键较多时,矩阵键盘的优势就凸显出来了,比如5×5矩阵键盘占用i/o口10个,可支持25个按键; 矩阵键盘的硬件设计非常简单,如图1以5×5矩阵键盘为例,蓝色行线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*5矩阵键盘扫描函数,返回扫描键值(行列反转扫描)-----------------------*/u16 key_scan(void){u16 cord_h,cord_l;u16 key_value = 0xffff;gpioa->crl = 0x88333334;gpioa->crh = 0x44444888;gpioa->odr = gpioa->idr & 0xffc1;cord_l = gpioa->idr & 0x07c0;if(cord_l != 0x07c0){delay_ms(10);if(cord_l != 0x07c0){cord_l = gpioa->idr & 0x07c0;gpioa->crl = 0x33888884;gpioa->crh = 0x44444333;gpioa->odr = cord_l | 0xf83f;delay_us(1);cord_h = gpioa->idr & 0x003e;cord_h >>= 1;cord_l >>= 1;key_value = (cord_l + cord_h) & 0xffff;return(key_value);}}return(0xffff);} 以下代码为端口配置寄存器的操作,pa组i/o有16个引脚:pa0~pa15;3代表推挽输出,4代表浮空输入,8代表上拉输入;
gpioa->crl = 0x88333334; //低8位配置gpioa->crh = 0x44444888; //高8位配置 以下代码中,gpioa->odr为端口输出数据寄存器,用于写操作;gpioa->idr为端口输入数据寄存器,用于读操作;
0xffc1的二进制:1111 1111 1100 0001,表示要对pa1~pa5置0。
0x07c0的二进制:0000 0111 1100 0000,表示要对pa6~pa10读值。
gpioa->odr = gpioa->idr & 0xffc1;//行线输出全为0cord_l = gpioa->idr & 0x07c0; //读入列线值 行列反转后的原理与上面完全一样,这里就不一一阐述了。
最后讲一下组合行线列线值,假如s1按键按下去了,得到的二进制为(注意黑体字)
cord_h: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=0000 0011 1101 1110,即0x03de;最后函数返回key_value值,该值就作为判断s1的键值。
之所以右移1位,是因为pa0没有用于矩阵键盘,所得到的键值也就被左移了1位,事实上,也可以不用右移,只是得到的组合码不同而已,右移是为了方便计算。
矩阵键盘的键值定义如下:
#define s1 0x03de#define s2 0x03be#define s3 0x037e#define s4 0x02fe#define s5 0x01fe#define s6 0x03dd#define s7 0x03bd#define s8 0x037d#define s9 0x02fd#define s10 0x01fd#define s11 0x03db#define s12 0x03bb#define s13 0x037b#define s14 0x02fb#define s15 0x01fb#define s16 0x03d7#define s17 0x03b7#define s18 0x0377#define s19 0x02f7#define s20 0x01f7#define s21 0x03cf#define s22 0x03af#define s23 0x036f#define s24 0x02ef#define s25 0x01ef 要点:
①行列反转扫描的思想是行线作为输出时,读出列线的值;然后反过来,列线作为输出时,读出行线的值,最后把两个值组合起来就是该按键的键值;
②参与计算的十六进制数一定要与行线或列线在同组端口的位置匹配,比如0xffc1的二进制:1111 1111 1100 0001,表示要对pa1~pa5置0。
如何将变量存储在指定内存地址 (基于Keil MDK-ARM)
VOCs在线监测仪可控制工业废气排放
FPGA数字电子系统的设计方法
浅谈汽车变速器工作原理及结构
机器人“伤人”事件:“操作不当”还是“设计缺陷”?
矩阵键盘扫描的原理及设计
基于S3C2410处理器和Linux平台实现视频处理和网络传输系统的设计
CCD和CMOS的技术对比
铁路轨道安全检查的守护核心–德承GP-3000
英伟达公司近年股价走势,人工智能芯片初创公司数量爆炸式增长
让数字预失真的故障排除和微调不再难 必备攻略请查收
自制法修复收录机按键
“平价机皇”再出新品?NANK南卡LITE真无线蓝牙耳机震撼来袭!
深析主动配电网的无功电压
华中科大与Synopsys建立ARC处理器联合培训中心,为中国IC产业发展输送人才
石油石化智能巡检管理系统的解决方案和实现功能介绍
开发3D打印新型软件工具,用于设计航空航天栅格结构
武汉芯源半导体首款车规级MCU,CW32A030C8T7通过AEC-Q100测试考核
苹果iOS 12VS谷歌Android P,到底谁更胜一筹
传智播客携手库柏特推动智能机器人技术与产业发展