年前去到一个朋友那里,提到现在客户对成本要求非常之高,尤其是玩具行业,已经是一分一厘的去计算产品成本。朋友感慨为了省成本,方案商是绞尽脑汁地去想各种实现方法,说遇到过为了节省成本,硬是用单片机一条 IO 实现了两个按键的功能,让他颇为诧异,好久都没想明白原理。
 
一条 IO 实现两个按键,听上去确实挺新奇,既然别人能够实现,我想我也应该可以做到,看来得找找实现的方法。我有一个习惯,遇到某些问题的时候,会在睡觉前想解决方法,想着想着就会睡着了,问题的答案有没有找到则不一定。
 
我知道有用一条 IO 实现多个按键的方法,这样的方法大多是选用的 IO 支持 ADC 功能,用电阻分压后通过读电压判断键值。如果 IO 不支持 ADC 功能,也不是不行,可以用电容充放电的方法实现 ADC,从而用普通 IO 间接进行测量。(参见我之前关于键盘扫描的文章)
 
这样用一条 IO 实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
 
 
先看上图左边部分,如果 MCU_IO1 为双向 IO 口,假设单片机程序按以下流程处理,看看会得到什么样的结果?
 
1.MCU_IO1 设定为输出,输出高电平一段时间,此时电容 C1 会充电,最后 C1 上的电压接近电源电压。
 
2.MCU_IO1 设定为输入,如果 J1、J2 均不按下,此时 MCU_IO1 可以理解成一个阻值很大的电阻接地,电容 C1 上的电荷会通过这个电阻逐渐释放掉,这样 C1 上的电压会逐渐降低到零。因为 C1 上的电压下降需要一个过程,当 MCU_IO1 设为输入后马上读一下 MCU_IO1 的状态,此时会读到什么结果?显然是高电平状态 1。
 
3. 再将 MCU_IO1 设定为输出,输出低电平一段时间,显然不管电容 C1 处于什么状态,只要 MCU_IO1 输出低电平时间足够长,最后 C1 上的电压应该接近零。
 
4. 再将 MCU_IO1 设定为输入,如果 J1、J2 同样不按下,MCU_IO1 读到的是低电平状态 0。
 
如果 J1 按下,再来看看这四步,此时电容 C1 已经被强制接到电源上,MCU_IO1 对其的充放电已经不起作用,在步骤 2 中 MCU_IO1 读到的状态依然是 1,但在步骤 4 中 MCU_IO1 读到的状态就不再是 0,而是变为 1。
 
如果 J2 按下,同样看这四步,此时电容 C1 被强制接到地,MCU_IO1 对其充放电也失去作用,在步骤 2 中 MCU_IO1 读到的状态变为 0,但在步骤 4 中 MCU_IO1 读到的状态保持为 1。
 
到这里我想大家应该已经明白了实现方法,根据此四步中读到的 MCU_IO1 状态,就可以判断出 J1、J2 是否按下。
 
既然已经找到方法,是不是就万事大吉了呢?不然,我们还得回过头去看看此方法是不是足够可靠。如果 J1 按下,电容 C1 直接接到电源上,当 MCU_IO1 输出低时,MCU_IO1 输出的低电平直接与电源短路,弄不好就会烧坏 MCU_IO1,同理当 J2 按下时 MCU_IO1 输出高也存在同样的问题。
 
还有比这更严重的问题,如果用户同时按下 J1 和 J2,哈!居然是电源和地直接短路,这样的后果很可能就是整个产品的电源部分一股青烟了事,就别想产品还能不能工作了。
 
不用担心,看一看前面电路图中的右半部分,在开关 J3 和 J4 上分别串联了一个 220 欧的电阻,这个电路不管 J3 和 J4 如何按,都不会出现短路的情况,按前面的四个步骤即可判断出 J3 和 J4 有没有按下,不过如果 J3 和 J4 同时按下并不能进行识别判断。