通过一个端口读取多个按钮

Posted 卓晴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过一个端口读取多个按钮相关的知识,希望对你有一定的参考价值。

简 介: 利用单片机的ADC端口,可以读取多个按钮的状态。在设计过程中,需要综合考虑到按扭的个数与读取的可靠性,特别是对选择电阻的阻值进行优化,使得不同分压数值之间相差最大。如果按键面板需要通过长的引线与单片机电路相连,还需要对接口电路进行保护以提高电路的EMC特性。

关键词 MCUADC按键

读取按键
文章目录
电路原理
电路原理图
按键个数
电路改进
增加接口可靠性
更多按键
八个按键
电路原理图
按键对应的电压值
方案特点
组合按键
三个按键组合输入
总 结

 

§01 取按键


  键是单片机系统中人机交互常用到的方法,通常情况下,通过普通的IO端口可以获得按键开关状态。在某些电子系统设计中,如果碰到按钮比较多,但单片机的IO口不够使用的时候,则需要通过端口扩展的方式来增加读取按钮的数量。比如通过并串转换芯片,8-3编码芯片等等。

  今天看到 公众号 电路啊 中的一篇推文: 电视机的按键功能是用什么电路实现的?经典ADC按键电路 介绍了在一款电视机中,采用单个ADC端口来读取多个按钮状态的方法。

▲ 图1.1 电视机控制面板上的七个按钮,接口线只有三条线

一、电路原理

1、电路原理图

  按键面板中的三个引线中,其中一个是电路地线,另外两个是信号线,分别接入主板中MCU的两路ADC端口。这两条线在主板上都通过3.3kΩ的电阻接到电源(3.3V)。在面板上,有多个按钮与电阻的串联之后连接在信号线与地线之间。

▲ 图1.1.1 工作原理说明图

  并联在 一起的按钮所串联的电阻不同,所以每个按钮按下之后,信号线的电压就是上拉电阻与按键串联电阻对电源的分压。由于每个按键串联电阻不同,所以对应信号线电压也就不同了。经过单片机ADC读取电压值之后,在与事先确定下的每个按键分压范围进行对比,从而可以确定是哪一个按钮被按下。

【表1-1-1 不同按键对应的电压】

SW1SW2SW3SW4
75 ohm1000 ohm3300 ohm6800 ohm
0.07 V0.77 V1.65 V2.22 V

2、按键个数

  根据上述原理,一条ADC端口可以读取按钮的个数是非常多的,它的上限受到以下因素影响:

  • 单片机ADC分辨率;
  • 分压信号的稳定性和噪声范围;
  • 机械按键接触电阻;
  • 分压电阻偏差与稳定性等。

  为了可靠的通过ADC读取的模拟分压电压来确定按键,需要合理选择分压电阻,使得每个按键所对应的电压之间的间隔越大越好。在上述实际设计的电路中,每个ADC端口只读取了四个按钮的状态,总共采用了两个ADC端口读取了7个(< 8个)按键状态。

▲ 图1.1.2 利用Arduino测试上述方案

二、电路改进

1、增加接口可靠性

  由于按键板与电路主板之间通过三根线连接,为了提高电路工作的可靠性,在按键电路接口中增加了R、C、TVS来消除静电、电磁干扰对主控板的影响。

▲ 图1.2.1 增加有提高EMC接口电路

  对于电路中的RC滤波器件参数选择,需要综合考虑滤除噪声的频率范围以及电路稳定时间。不能够为了降低噪声一味增加RC时间常数,,还需要考虑按键动作时,对应的分压信号达到稳定的过渡时间的大小。

 

§02 多按键


  前面案例中,每个ADC只读取四个按键,下面给出一些可以读取更多按键的方案。

一、八个按键

1、电路原理图

  下面是在推文经典ADC按键电路中给出的已经批量应用的八按键ADC读取电路配置方案。

▲ 图2.1.1 被批量使用的八个按键方案

2、按键对应的电压值

  按照电路中的电阻参数,可以计算出每个按键对应的信号分压电压值:

【表2-1-1 八个按键对应的信号电压】

SW1SW2SW3SW4SW5SW6SW7SW8
0 ohm510 ohm680 ohm1000 ohm1200 ohm2200 ohm4700 ohm15000 ohm
0.00 V0.32 V0.67 V1.05 V1.38 V1.79 V2.27 V2.78 V

▲ 图2.1.2 八个按键对应的信号电压

from headm import *                 # =
from tqdm import tqdm

R0 = 4.7e3                          # ohm
Rdim = [0, 510, 680, 1e3, 1.2e3, 2.2e3, 4.7e3, 15e3]
U0 = 3.3                            # V

Vdim = [sum(Rdim[:r+1])/(R0+sum(Rdim[:r+1]))*U0 for r in range(len(Rdim))]
Rstr = ['%4d ohm'%r for r in Rdim]
Vstr = ['%.2f V'%v for v in Vdim]

printt('|'.join(['SW%d'%(d+1) for d in range(len(Rstr))]))
printt('|'.join(["--"]*len(Rstr)))
printt('|'.join(Rstr))
printt('|'.join(Vstr))

plt.figure(figsize=(10,6))
plt.plot(Vdim)
plt.xlabel("Swn")
plt.ylabel("Voltage")
plt.grid(True)
plt.tight_layout()
plt.show()

3、方案特点

  在这个电路中,后面按键对应的电阻值是由前面所有串联电阻累加和。

  这个电路的巧妙之处在于,按键具有优先级之分。假设按下了按键SW1,那么再按下SW2-SW8中的任何一个都是不起作用的,即SW1的优先级最高,SW2次之,以此类推。

二、组合按键

  上面电路中不允许使用组合按键,即通过两个或者两个 以上的按摩同时按下代表更多的功能。

1、三个按键组合输入

  下面电路中,只使用3按钮便可以获得8个状态的输入。

▲ 图2.2.1 利用电阻组合完成多个多个按钮输入

  需要通过适当选择 R 1 , R 2 , R 3 R_1 ,R_2 ,R_3 R1,R2,R3的阻值,使得八种 S W 1 , 2 , 3 SW_1,2,3 SW1,2,3不同的按键组合,所得到的八个电压之间的间隔最大,这样才能够保证ADC通过分压数值确定状态时更加可靠。

  利用程序对 R 1 , 2 , 3 R_1,2,3 R1,2,3进行搜索,搜索范围(100,10k),搜索步长:50欧姆。可以获得一组最优电阻取值:

R 1 = 1250 Ω ,   R 2 = 1650 Ω ,   R 3 = 2800 Ω R_1 = 1250\\Omega ,\\,R_2 = 1650\\Omega ,\\,R_3 = 2800\\Omega R1=1250Ω,R2=1650Ω,R3=2800Ω

  最小的电压间隔为: 0.152V。

  下面是八种按键组合所得到的电压,从小到大的电压值。

['1.19V', '1.37V', '1.53V', '1.68V', '1.83V', '2.05V', '2.43V', '3.30V']
vdiffmin:
0.15112480559591712
vr123:
[1250.0, 1650.0, 2800.0]
from headm import *                 # =
from tqdm import tqdm

R0                     = 1e3
U0                     = 3.3
searchStep             = 199
searchRange = [[0.1*R0, 10*R0], [0.1*R0, 10*R0], [0.1*R0, 10*R0]]
searchDim = [linspace(r[0],r[1], searchStep) for r in searchRange]

def minVoltage(r1,r2,r3):
    rdim = [10e10, r1, r2, r3,
            1/(1/r1 + 1/r2),
            1/(1/r1 + 1/r3),
            1/(1/r2 + 1/r3),
            1/(1/r1 + 1/r2

以上是关于通过一个端口读取多个按钮的主要内容,如果未能解决你的问题,请参考以下文章

监控 tcpdump 中的多个端口

时序问题:QT 写入串行端口,然后读取

Ngrok 无法读取端口的配置

net core 2.0 读取文件添加为资源

如何在单页中使用 php 从 while 循环中生成多个读取更多按钮?

filezilla如何配置多个端口