搜索
bottom↓
回复: 94

来讲点东西:基于ADC的单线键盘,及程序实现

[复制链接]

出0入0汤圆

发表于 2007-9-24 18:00:31 | 显示全部楼层 |阅读模式


点击此处下载ourdev_174381.txt(文件大小:749字节)

如图:这里举了4个按键的例子,16个,甚至32个按键都可以。

1.AVR的ADC基准,使用的内部1.1v基准。
2.电源VCC=3.3v。
3.程序:具有对每个键 单击压,单击放开,长压 检测。

设计要点:
由于误差,如内部参考电压实际在1.0-1.2v之间,还有其他ADC转换误差等,所以设计的这个电路必须有这点容错能力。要具备这点,必须保证:当任何一个按键按下时,在误差范围内得到的ADC的值,都不能与其他按键重叠,最好是有相当的距离。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2007-9-24 19:38:09 | 显示全部楼层
我前段时间也刚做了A/D开关,谈一下心得.
1.基准电压用Vcc,这样不受内部基准的变化和外部电压而改程序,
  内部基准有的芯片是1.1V,有的是2.56V.
  外部有时用3V,有时用5V.

2.都是用的10K,做了6个开关,最下面一个用了30K.

3.对每个按键都做了采样--延时--采样,跟做开关一样的.
  虽然程序长了点,但安全.保证,每个开关采样都是对的,
  有抖动就跳走.

出0入0汤圆

发表于 2007-9-24 19:43:14 | 显示全部楼层
用电源电压做基准有个好处就是电阻分压跟电源有关,这样ADC的值不管使用什么电源电压理论上都是固定的,实际可能会有1LSB的误差

出0入0汤圆

 楼主| 发表于 2007-9-24 19:45:28 | 显示全部楼层
其实图中VCC,和ADC参考电压用同一个电压会更好。这样不受参考电压不准确的影响。

出0入0汤圆

发表于 2007-9-25 16:44:40 | 显示全部楼层
楼主的程序漏了一个大括号

出0入0汤圆

发表于 2007-9-25 17:45:58 | 显示全部楼层
adc中断?觉得还是加个外部中断好~~

出0入0汤圆

 楼主| 发表于 2007-9-25 23:00:26 | 显示全部楼层
to 4楼:这个是从我的一个项目里面提出来的,可能存在。
to 5楼:定时器中断比较好。时间很好把握。

出0入0汤圆

发表于 2007-9-26 01:57:32 | 显示全部楼层
我也做过,用了五个按钮。这种方式由于电阻采用分压方式工作,所以实际上的按钮不可能很多了,另外还要考虑容错性能。所以理论和实际不一样的。否则的话,外部干扰或者各种原因就会造成运行不正常的。我在板上设计了恒流源,但最后没有使用。用恒流源有个好处是各个按钮的电压基本能够平分。

出0入0汤圆

 楼主| 发表于 2007-9-26 10:08:44 | 显示全部楼层
VCC,和ADC参考电压用同一个电压,这样,就不存在ADC参考电压不准确了,如Vref使用Vcc=3.3V,ADC值 = Vcc*(电阻分压)/Vref*1024=电阻分压*1024
主要考虑ADC自身误差(大概+ -2LSB),这样算来。理论上可以接1024/4=256个按键。
考虑电阻误差和电阻值离散性,可能到不了这个数,但是接16个按键是绝对可行的。
理论是指导实践的,如果实践结果与理论不符,那理论肯定是错误的,不完善的。

出0入0汤圆

发表于 2007-9-26 12:37:00 | 显示全部楼层
我加外部中断扩展过8个键

利用马老师的那个状态机原理,扩展16个应该没问题的~~


有没试过多通道组合键的?

出0入0汤圆

 楼主| 发表于 2007-9-26 13:08:54 | 显示全部楼层
组合键 比较麻烦可以参考 R-2R DA转换器原理

出0入0汤圆

发表于 2007-9-26 17:35:54 | 显示全部楼层
以前做过一个模拟量键盘,很难保证每次采集的百分之百的正确阿!!
头像被屏蔽

出0入0汤圆

发表于 2007-9-26 17:38:51 | 显示全部楼层
是的,一看就感觉只能玩玩,无法提供100%的准确度。

出0入0汤圆

发表于 2007-9-26 18:20:15 | 显示全部楼层
赞同阿莫,我也做过类似的系统,实在是不稳定.

出0入0汤圆

 楼主| 发表于 2007-9-26 18:30:13 | 显示全部楼层
很多机器上都是这么做的,曾经看到一款夏普的计算器上就是这么做的。
要可靠,可以在软件上适当做一些防止误判断的算法处理。

出0入4汤圆

发表于 2007-9-26 20:22:41 | 显示全部楼层
是的,在软件上做文章,我前几日也用同样的电路做了4个按件的东西,实验板做的,IO不够了,反正不是产品。基本上能实现功能,软件确实很重要。写的不好,容易出现按键无响应,或者继续上次的按键。
我用了4个字节的ADC缓冲。计算平均值。后来没有仔细的修改程序,基本上可以实现按键的功能。

出0入0汤圆

 楼主| 发表于 2007-9-26 21:16:11 | 显示全部楼层
补充!!!
经过半个多小时的分析得出:

ADC的参考电压和VCC共用3.3V

采用如下电阻
R = 1000;
Rn = [68,75,82,100,120,150,180,220,300,360,510,820,1200,2800,8200];
构成16个开关,ADC值 = n/16 * 1024。
如果,不考虑电阻误差和ADC转换误差,只考虑电阻值离散性导致的误差,最大误差 = 0.32%
如果,考虑电阻值误差+-5%,这点所导致的最大误差等于 +/-5%
总体来说由外部电阻所导致的误差约 = +/-52LSB,再加上ADC转换误差+/-2LSB,得+/-54LSB
而每个按键按下所对应的ADC值的间距 = 1024/16 = 64LSB
看来用一般的电阻还不得行。得用 1% 的电阻

呵呵,可能理论学得还不到家,可能有错。

有注释的代码:
void timerIRP(void) /* 定时器中断 */
{
unsigned char i;
unsigned char key;
static unsigned char key_last;
static unsigned char key_val;
static unsigned char key_dm_ctr = 0; /* 计时按键按下的持续时间 */

        i = adcRead(); /*直接读取ADC值,因为定时器周期远大于ADC转换时间*/
       
        /* 根据ADC值,对按键编号 */
        if (i < 128)
                key = 1;
        else if (i < 388)
                key = 2;
        else if (i < 683)
                key = 3;
        else if (i < 995)
                key = 4;
            else
               key = 0;
       
        adcStart(ADC_CH_KEY); /* 启动下一次AD转换 */

        if (key_last == key) /* 两次检测到的值一样,以消抖动 */
        {            
                if (key != 0)
                {
                        if (key_dm_ctr == 0)
                        {
                                key_val = key;
                                /* key_val 按键按下 */
                                switch(key_val)
                                {
                                /*根据按键处理*/
                                }
                        }
               
                        if (key_dm_ctr != 0xff)
                                key_dm_ctr++;
                       
                        if (key_dm_ctr == 100)
                        {
                                /* 长压 */
                                switch(key_val)
                                {
                                        /*根据按键处理*/
                                }
                        }
                }
       
                else
                {
                        if (key_val)
                        {
                                if (key_dm_ctr < 100)
                                {
                                        /* key_val 单击后按键放开 */
                                        switch(key_val)
                                        {
                                                /*根据按键处理*/
                                        }
                                }
                                key_val = 0;
                        }
                        key_dm_ctr = 0;
                        }
                }
        }
       
        key_last = key;       
}

出0入0汤圆

 楼主| 发表于 2007-9-26 23:33:16 | 显示全部楼层
不好意思16楼分析错了,
1.由电阻离散性导致的误差大概在+/- 6LSB
2.这里:
“总体来说由外部电阻所导致的误差约 = +/-52LSB,再加上ADC转换误差+/-2LSB,得+/-54LSB ”
应该是:总共是 +/-52LSB 加 +/-2LSB 加 +/- 6LSB 得 +/-60LSB
3.Rn里面有个2800,没有这种+/-5%的电阻,应该是2700

附上电路图

出1000入0汤圆

发表于 2007-9-27 08:03:37 | 显示全部楼层
1,电源和CPU共用
2,楼主的接法不支持多键同按,分压电阻应该为权电阻。

出0入4汤圆

发表于 2007-9-27 08:17:21 | 显示全部楼层
我觉的按键多并不可靠 一个系统20个按键已经很多了,用2路ADC 采不是更好吗 或者3路,也就只占用3个IO.

不过最好的方法是实践  实践得真知

出0入0汤圆

发表于 2007-11-11 16:34:40 | 显示全部楼层
我以前也做过这样的程序,都是在端口不够的情况下才拿出这一必杀秘技。感觉上楼主的原理不太好,这样不能挂太多的按键,如果按键一多,到最后的几个按键的AD值靠得很近,分辩困难,对电阻的精度要求高。以下是我设计的原理图可解决这一问题,用碳膜电阻都可以做很多个按键,我原来的项目挂9个按键。

出0入0汤圆

发表于 2007-11-11 17:54:02 | 显示全部楼层
这个好,互相独立,电阻怎么取?1248比例?

出0入148汤圆

发表于 2007-11-11 18:31:40 | 显示全部楼层
实践证明这种方法并不是那么好。昨天我的显示器设定的按钮乱了,一个按钮没反应,本来是减的按钮变成了加,有个就干脆是乱跳。拆开发现用的就是这种单线键盘,测了一下发现是轻触开关的问题,显示器用了两年,轻触开关按下的电阻随着按的力度和角度竟然有非常大的变化,换了开关后一切正常,所以建议大家如果用这种键盘要考虑开关电阻的变化。

出0入0汤圆

 楼主| 发表于 2007-11-11 18:35:43 | 显示全部楼层
之所以不用22楼 是考虑PCB排版问题。其实实现起来原理都一样,只是计算方法稍微复杂点了。

出0入0汤圆

发表于 2007-11-11 19:10:59 | 显示全部楼层
同意23楼的说法,我的夏普14寸用了10多年,铵键产生的问题与23楼一样

出0入4汤圆

发表于 2007-11-12 13:03:52 | 显示全部楼层
那说明人家也是这么在用的,而且是大量的用。

出0入0汤圆

发表于 2007-11-12 21:56:25 | 显示全部楼层
感觉1楼的按键处理好一点,21楼的问题所在:按键多,电阻的取值计算复杂,如同时按下的几个按键可能造成分压值与另外的组合按键相同或者相近,而1楼的按键在组合的时候具有上面的比下面的有优先权,如果能解决这个问题更好!
欢迎大家出主义

出0入0汤圆

 楼主| 发表于 2007-11-19 21:35:05 | 显示全部楼层
27楼的“1楼的按键在组合的时候具有上面的比下面的有优先权”说得对。
关于“电阻的取值计算复杂”问题并不难,16个按键就是一个 16原方程组。

出0入0汤圆

发表于 2007-11-20 16:50:08 | 显示全部楼层
好学学

出0入0汤圆

发表于 2007-11-20 17:52:13 | 显示全部楼层

出0入0汤圆

发表于 2007-11-20 23:15:27 | 显示全部楼层
这个电路似乎是彩色电视机上面的按键面板,老掉牙了,它有个不好的地方就是用久了,按键上面会有一些氧化或接触面有杂物跑进去,造成出现接触不良而读数错误

出0入0汤圆

发表于 2008-5-18 11:25:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-5-18 12:03:11 | 显示全部楼层
感觉这样的键盘不太好,虽然节省了IO口,但是程序复杂了,而且稳定性难以控制。一楼的键盘有优先级,不可以检测双键同时按下的情况。

出0入0汤圆

发表于 2008-5-24 16:35:06 | 显示全部楼层
事情往往不会两全其美的,都得有取舍,看你需要哪样就则重那方面吧。

出0入0汤圆

发表于 2008-5-24 17:01:40 | 显示全部楼层
楼上的说得正对..
能用能实现稳定就行...好多电视机上的按键面版是采用1楼的方式来实现....

出0入0汤圆

发表于 2008-5-24 18:39:57 | 显示全部楼层
好贴

出0入0汤圆

发表于 2008-5-24 18:46:01 | 显示全部楼层
精度还可以的,几个按键的电压值尽量大一点

出0入0汤圆

发表于 2008-5-24 19:57:53 | 显示全部楼层
不错,有是一个节省I/O口的方法~ 受教了^_^

出0入0汤圆

发表于 2008-5-24 20:37:42 | 显示全部楼层
AD键盘其实很好啊,不怎么出现问题,我们的产品除了触摸的,一率用这种方式,因为可以节省口线,只要分压选得远一点,完全可以的,我们做过7个8个的都没有问题,我的程序是在定时中断里,每10Ms采一次AD,如果6到10次采样的AD值都在同一个范围,则确认,否则为无效键.

出0入0汤圆

发表于 2008-5-24 20:40:04 | 显示全部楼层
10Ms采一次AD,如果6到10次采 会不会有不灵的感觉呢

出0入0汤圆

发表于 2008-5-24 22:55:54 | 显示全部楼层
我的系统也用过,没出现问题,只不过每个键的AD值的范围要小一点,要不然会出现串键的现像。比如说在采样第二个按键时,实际采样的AD值为895,那么为第二个按键分配的AD值范围是895+4到895-4最好,不会出现串键,无需消抖,我接7个按键非常稳定。

出0入0汤圆

发表于 2008-5-25 10:32:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-5-25 20:23:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-8-24 18:30:38 | 显示全部楼层
mark .too!!!

出0入0汤圆

发表于 2008-8-24 22:09:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-8-24 22:36:19 | 显示全部楼层
上次采用AD键盘,发现不稳定,不知是不是键盘接触不好,还是AD程序不好。但设计成IO口独立键盘后,一样的键盘,在IO口独立键盘程序下很稳定。所以我又改为IO口独立键盘了。
IO口不够用,可以分时复用的,因为单片机在同一时刻只能做一件事。

出0入0汤圆

发表于 2009-6-9 10:15:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-4 09:44:18 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-7-4 13:51:59 | 显示全部楼层
不错,留名。

出0入0汤圆

发表于 2009-7-4 15:35:49 | 显示全部楼层
下图是我打算使用的电路,AD按键


(原文件名:ourdev_180513.jpg)

基准用的外部,=Vcc,共八个按键!!不置可否?请点评!

出0入0汤圆

发表于 2009-7-5 10:20:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-11 00:48:33 | 显示全部楼层
不错

出0入0汤圆

发表于 2009-7-11 06:30:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-11-2 10:17:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-11-2 11:37:24 | 显示全部楼层
原来还有这种方法,学习学习

出0入0汤圆

发表于 2009-12-14 15:04:08 | 显示全部楼层
AD很贵啊

出0入0汤圆

发表于 2010-1-9 16:28:16 | 显示全部楼层
电子竞赛做了AD键盘,可惜没什么大用。

出0入0汤圆

发表于 2010-3-12 17:02:00 | 显示全部楼层
jh

出0入0汤圆

发表于 2010-6-3 17:00:47 | 显示全部楼层
现在好像都很喜欢这样用哦

出0入0汤圆

发表于 2010-8-3 20:16:05 | 显示全部楼层
记录

出0入0汤圆

发表于 2010-9-26 19:43:40 | 显示全部楼层
标记学习了.

出0入9汤圆

发表于 2010-9-26 19:46:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-26 19:57:00 | 显示全部楼层
值得学习

出0入0汤圆

发表于 2010-9-26 20:09:56 | 显示全部楼层
有机会一试

出0入0汤圆

发表于 2010-9-26 21:06:34 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-9-29 11:40:00 | 显示全部楼层
回复【50楼】jackielau 九天
-----------------------------------------------------------------------

这样不行,当多个按键按下时,误动作。

出0入0汤圆

发表于 2010-11-15 20:48:34 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-15 21:48:52 | 显示全部楼层

AD-Key (原文件名:AD-Key.jpg)

如上图,是我项目中使用AD按键的设计参数,其中上拉电阻R0参数标错了,实际为4K7。
这个电路的优点是:只需根据AD高四位的值便可以判断出相应按键号。

出0入0汤圆

发表于 2010-11-18 17:04:11 | 显示全部楼层
如果一定要用在产品上,建议不要超过4个键,我就上过当。当时损失可大了,全部招回!

出0入0汤圆

发表于 2010-11-18 20:48:24 | 显示全部楼层
mark,不错

出0入0汤圆

发表于 2010-11-20 16:58:57 | 显示全部楼层
基于ADC的单线键盘,及程序实现

出0入0汤圆

发表于 2010-11-20 21:58:12 | 显示全部楼层
回复【16楼】zhonghua_li 蓝色天空
-----------------------------------------------------------------------

MARK

出0入0汤圆

发表于 2010-11-26 11:44:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-14 11:13:18 | 显示全部楼层
mark,最近在学习ADC转换

出0入0汤圆

发表于 2011-3-11 13:47:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-11 20:41:18 | 显示全部楼层
思路很有意思

出0入0汤圆

发表于 2011-8-6 20:52:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-28 15:55:09 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-9-28 16:54:34 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-1 07:52:22 | 显示全部楼层
自己玩可以 千万不要做产品害人

出0入0汤圆

发表于 2011-10-1 10:51:41 | 显示全部楼层
TI的zigbee板子是这么干的,比较慢,不好用,采样率提不高

出0入0汤圆

发表于 2011-10-1 22:07:12 | 显示全部楼层
以前也想这样做,但是没用上

出0入0汤圆

发表于 2011-12-21 20:26:20 | 显示全部楼层
回复【80楼】tiandixuan
自己玩可以 千万不要做产品害人
-----------------------------------------------------------------------

你技术不行,就老实说。自己没本事就以为别人也一样?AD按键怎么就害人了。

出0入0汤圆

发表于 2011-12-21 21:13:28 | 显示全部楼层
好东西,谢谢

出0入0汤圆

发表于 2011-12-24 11:11:08 | 显示全部楼层
ad键盘要做到稳定性,key的范围要设置好,另外多采样几次,避免抖动。

出0入0汤圆

发表于 2011-12-24 11:51:14 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2011-12-24 23:59:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-28 12:03:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-28 12:08:20 | 显示全部楼层
MARK下

出0入0汤圆

发表于 2011-12-30 18:49:44 | 显示全部楼层
cool

出0入0汤圆

发表于 2011-12-30 20:46:00 | 显示全部楼层
mark

出10入10汤圆

发表于 2011-12-30 21:06:47 | 显示全部楼层
按键要用质量好的,密封好的不易进灰尘的,否则接触电阻增大后会很麻烦。不建议用在正式产品上

出0入0汤圆

发表于 2012-1-9 11:08:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-15 21:35:26 | 显示全部楼层
留记号
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 00:48

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表