打印

基于ADC的单线键盘,及程序实现

[复制链接]
3998|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhong_hua|  楼主 | 2007-10-31 19:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
支持 单击压,单击放,长压。
经过半个多小时的分析得出:在AVR中 

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;         
}

相关帖子

沙发
zhong_hua|  楼主 | 2007-10-31 19:35 | 只看该作者

图中有点错误:R1应该是R,R2应该是R1,R3应该是R2...

使用特权

评论回复
板凳
zhong_hua|  楼主 | 2007-10-31 19:38 | 只看该作者

不好意思,有分析有点错误

1.由电阻离散性导致的误差大概在+/- 6LSB 
2.这里: 
“总体来说由外部电阻所导致的误差约 = +/-52LSB,再加上ADC转换误差+/-2LSB,得+/-54LSB ” 
应该是:总共是 +/-52LSB 加 +/-2LSB 加 +/- 6LSB 得 +/-60LSB 
3.Rn里面有个2800,没有这种+/-5%的电阻,应该是2700 

附上电路图 

使用特权

评论回复
地板
hotpower| | 2007-10-31 21:36 | 只看该作者

感觉还是不敢用,电阻不好筛选

使用特权

评论回复
5
zhong_hua|  楼主 | 2007-11-1 00:58 | 只看该作者

按键越多,当然出错的概论就高,4个,8个是没问题的

使用特权

评论回复
6
fsaok| | 2007-11-1 05:51 | 只看该作者

改用其它的连接方式吧

等会画一个图看看

使用特权

评论回复
7
ayb_ice| | 2007-11-1 07:55 | 只看该作者

用IF判断按键效率太低。。。

使用特权

评论回复
8
xwj| | 2007-11-1 08:51 | 只看该作者

ayb_ice ,你说个效率高的方法看看

使用特权

评论回复
9
xwj| | 2007-11-1 09:02 | 只看该作者

你这样Rx是在分母上,所以算不出整数;换种接法,把Rx丢在

就好取值了

使用特权

评论回复
10
xieguangye| | 2007-11-1 09:07 | 只看该作者

学习

不 错

使用特权

评论回复
11
车载音响| | 2007-11-1 09:15 | 只看该作者

9楼:怎么样把Rx弄到分子上?

使用特权

评论回复
12
ayb_ice| | 2007-11-1 09:36 | 只看该作者

可以平均分配电平然后用SWITCH

换句话说只用4位的AD即可组成16(15个)个按键。。。
高位AD值也可以去掉后面的数据。。。
另外AD扫键接多了不可靠,受电阻精度,温度,电压,潮湿影响较大。。。
利用电流型DA配合效果会好些(可以很线性,方便的选择电阻)。。。
我曾经在项目中使用AD扫键,而且我是把每个按键的AD值存入EEPROM中做比较的,还可以随时再校准的,但后来还是改传统的方式了。。。

使用特权

评论回复
13
starlite_jason| | 2007-11-1 10:36 | 只看该作者

AD接键盘接多了就不太好了

7、8个还是很方便的,另外做校正可以将电阻本身引起的误差降低

使用特权

评论回复
14
woshidasha| | 2007-11-1 12:04 | 只看该作者

你的电路有错误

你的电路有错误,按键度出来的应该全是第一个按键,你应该把所有的电阻串起来接地,按键的公共端接ADC

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

37

帖子

0

粉丝