一、用外部中断方式检测独立按键
二、用查询方式检测独立按键
三、键盘的扩展方法
不外加芯片,不占用片内ADC,5个I/O口扩展25个按键
四、AD键盘的设计
使用STC15W4K32S4单片机片内自带ADC,设计键盘
五、用串口工作方式0扩展键盘
硬件消抖动电路
通常的按键为机械弹性开关,由于机械触点的弹性作用,一个按键开关在闭合时不会一下子稳定地接通,在断开时也不会马上断开。因而在闭合及断开的瞬间均伴随有如图1所示一连串的抖动,抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。
为了不产生图1所示波形而采取的措施就是按键消抖,消抖动有两种方法:一是采用硬件消抖动,二是采用软件延迟消抖动(见“键盘识别程序”选项卡)。为了降低硬件系统的复杂性,节省空间,单片机应用系统通常采用软件延迟消抖动。硬件消抖动常用的器件有/RS触发器、电容、施密特触发器等。

图1 按键时产生的抖动
图2是/RS触发器消抖动电路,开关SW1未按下时输出高电平,按下时输出低电平,开关SW1在离开上端触点时如果有抖动,只要还没有接触到下端触点,输出保持高电平不变;同理,开关SW1在离开下端触点时如果有抖动,只要还没有接触到上端触点,输出保持低电平不变。

图2 /RS触发器消抖动电路
图3是电容消抖动电路,利用电容两端电压不能突变的特性,将其并联在按键机械触点两端,消除接触抖动产生的毛刺电压。上拉电阻R1和电容C1组成充放电电路,其时间常数R1C1应大于抖动时间,小了没作用,大了反应慢。

图3 电容消抖动电路
图4是RC加施密特触发器消抖动电路,施密特触发器74HC14的正向阈值电压是1.6V,反向阈值电压是0.8V,只要电阻R1和电容C1组成充放电电路时间常数设置合适,利用施密特触发器正向和发向阈值电压不同的特点,输出可以达到整形效果,消除按键抖动。这种电路只适用于输入阻抗高的CMOS数字电路,不建议在输入阻抗低的TTL电路中使用。

图4 RC加施密特触发器消抖动电路
图5是采用Maxim公司开关去抖动芯片MAX6816构成的消抖动电路,MAX6816可以用MAX6817或MAX6818替代,它们都是4脚封装,电源电压为2.7~5.5V,静态功耗仅为5μA。

图5 MAX6816芯片消抖动电路
★温馨提示:本部分内容选自《单片机学习与实践教程》,朱向庆编著,北京邮电大学出版社,2018年出版,引用请注明出处。
按键识别扫描子程序流程
常见的按键识别扫描子程序流程如图1所示。进入子程序后,首先读按键,判断是否有键被按键。无则退出子程序,有则延迟10ms消抖动。然后再次读按键,继续判断是否有键被按键。无则退出子程序,有则用上文介绍的方法识别哪个键被按下。识别完毕,等待按键松开后,退出子程序。

图1 常见的按键识别扫描子程序流程
图1所示程序流程,最大的缺陷,就是等待按键松开部分。按下按键后,如果手没有马上松开,则程序一直在等待,不会退出子程序,有可能会影响到其他子程序的运行。采用图2所示流程,可改进图1中的缺陷。图2子程序设立一个全局变量或者静态局部变量LastValue,进入子程序,判断到有键被按下时,如果其键值Value与上次保留的变量LastValue一致,则说明手没有松开,退出子程序。只要手一松开,进入子程序时,读到的没有键被按下的键值Value就复制给LastValue,下次即使按下的键与上次按下的键相同,也会进入软件延迟消抖动。

图2 按键识别扫描子程序流程改进版1
如果要继续改进图2程序流程,使其更加完美的话,就是延迟10ms部分,不要采用循环等待的方法,而是用定时器/计数器实现。图3是改进版2的流程,在键盘处理子程序中设计一个状态机,子程序有4个状态,系统初始化时为1态:等待键盘被按下。进入键盘处理程序后,可以做到“快出”,软件延迟消抖动和等待按键释放都不占用系统时间。

图3 按键识别扫描子程序流程改进版2
★温馨提示:本部分内容选自《单片机学习与实践教程》,朱向庆编著,北京邮电大学出版社,2018年出版,引用请注明出处。
AD键盘
现在很多单片机片内集成高速的模数转换器(ADC),如果需要的按键数量不多时,只需使用1个AD引脚就可以扩展若干个按键。
图1为6个电阻串联分压按键键盘,无键被按下时,AD引脚通过R1电阻接VDD,AD转换值为最大值max;S1被按下时,AD引脚接地,AD转换值为0;S2被按下时,电阻R2下端接地,AD引脚电压是R2上分得的电压0.5VDD,AD转换值为0.5max;其他按键被按下时的理论值如此类推。设置的判决门限为各按键值之间的中点,如图1中虚线所示,AD值在0~0.25max之间判决为S1被按下,在0.25max~7/12max之间判决为S2被按键,其他如此类推。
图1中各电阻阻值相等,造成分压不均匀,判决区间长度不一,有的相对过小,可能造成串键。为了改善图1,可以合理设置R1~R6的比例,使得各判决区间长度差距不要过大;但不建议采用可调电阻,因为使用时间久了后,可调电阻的阻值可能会变化。扩展的按键数量要控制好,按键数量多了,会使得判决区间长度减小,有可能造成串键。

图1 电阻分压式AD键盘
实际应用中,也可采用图2所示电路,用特性一致的开关二极管1N4148取代分压电阻。图2扩展出7个按键,各按键被按下时,AD引脚产生的电压分布均匀,有利于判决。

图2 二极管分压式AD键盘
★温馨提示:本部分内容选自《单片机学习与实践教程》,朱向庆编著,北京邮电大学出版社,2018年出版,引用请注明出处。
不外接芯片扩展键盘的方法
实际应用中,如果需要扩展的键盘数量比较多,可以采用并入串出芯片74HC165、CD4014等芯片,扩展输入接口。购置芯片会引起产品采购成本的上升,同时会增加PCB板的面积,增加电子产品的功耗,对于要严格控制各种成本,“锱铢必较”的生产厂家而言并非最优选择。下文介绍一种构思巧妙,不须外接任何I/O口扩展芯片进行键盘扩展的方法。
以5个I/O为例,通常能够想到的,就是每个I/O口外接1个独立按键,或者设计如图1所示的3×2矩阵键盘,扩展6个独立按键。

图1 3×2矩阵键盘
图1能否再进行改进呢?如图2所示,直接在行引脚P2.0~P2.4增加5个独立按键,可将按键数量扩展到11个。注意,此时P2.0~P2.2各要增加以1个上拉电阻。扫描时,先往P2.0~P2.4写5个“1”,再读P2.0~P2.4,判断5个独立按键是否被按下;若5个独立按键都没有被按下,接着再用上文介绍的矩阵键盘扫描方法,对3×2矩阵键盘进行扫描。由此可见,独立按键与矩阵键盘可以共存,互不影响。

图2 3×2矩阵键盘加5个独立按键
图3是一种构思巧妙的三角形键盘,5个I/O可以扩展出10个按键。这种键盘的识别,可以采用行扫描方法:①先扫第1行,往P2.0~P2.4写“01111”,再读P2.1~P2.4,即可判断出K11~K14是否被按下;②若第1行无键被按键,接着扫描第2行,往P2.1~P2.4写“0111”,再读P2.2~P2.4(此时不用再去读P2.0,判读第1行),即可判断出K21~K23是否被按下;③若第2行无键被按键,继续扫描第3行,往P2.2~P2.4写“011”,再读P2.3和P2.4(此时不用再去读P2.0和P2.1,判读第1、2行),即可判断出K31和K32是否被按下;④若第3行无键被按键,最后扫描第4行,往P2.3和P2.4写“01”,再读P2.4(此时不用再去读P2.0~P2.2,判读第1~3行),即可判断出K41是否被按下。

图3 三角形键盘
别小看图3的三角形键盘,在不扩展独立按键的情况下,它只比图2少1个按键而已。再研究一下图3键盘的扫描方法,在P2.0送“0”时,用其他4个I/O口识别K11~K14,全部I/O都被充分利用。在P2.1送“0”时,用P2.2~P2.4这3个I/O口识别K21~K23,此时P2.0引脚闲置,没有被充分利用。能否在P2.1引脚再增加一个按键,让P2.1送“0”时,由P2.0进行识别?同样的想法,在P2.2~P2.4行分别增加2~4个按键,是否可以?据此,画出图4,每一行都有4个按键,全部I/O口都被充分利用!
但图4电路存在缺陷,例如,扫描第1行,往P2.0送“0”时,如果K14a和K14b有一个被按下,P2.1读到的数据都是“0”,但程序没法判断出K14a和K14b到底哪个键被按下。可见,不管扫描哪行,都没法判断对称的a、b按键中哪个键被按下。

图4 对称三角形键盘1
有什么方法可以将对称按键分开呢?图5增加了5个单向导电性器件——二极管(假设其材料是硅),巧妙地解决了这个问题。
例如,扫描第1行,往P2.0送“0”时,如果K14a被按下,P2.1引脚的电压是0.7V,读引脚后判为“0”;如果K14b被按下而”时,如果K14a弹起,P2.1引脚电压是5V,读引脚后判为“1”。那程序如何识别出K1b是否被按下呢?扫描第2行时,往P2.1送“0”时,如果K14b被按下,P2.0引脚的电压是0.7V,读引脚后判为“0”;如果K14a被按下而K14b弹起,P2.0引脚的电压是5V,读引脚后判为“1”。由此可见,增加了二极管,可以正确判断对称的a、b按键中哪个键被按下。

图5 对称三角形键盘2
图5是不是最多的,还能否再扩展?受图2的启发,将5个I/O口对地再接5个独立按键K51~K55,此时,可以扩展出25个按键。扫描时,先往P2.0~P2.4写“11111”,再读P2.0~P2.4,只要读到“0”,即可判断出哪个独立按键被按下;如果读进的数据全“1”,说明5个独立按键都没有被按下,接着再用上述介绍的方法扫描对称三角形键盘。

图6 对称三角形键盘增强型
综上所述,n个I/O口,只要增加n个二极管,即可扩展出n×(n-1)+n=n2个按键。不增加二极管,最多可以扩展出[n×(n-1)/2]+n个独立按键。最先设计出此电路的,是美国的一个工程师,他还申请了该电路的专利。
★温馨提示:本部分内容选自《单片机学习与实践教程》,朱向庆编著,北京邮电大学出版社,2018年出版,引用请注明出处。