支持 单击压,单击放,长压。 经过半个多小时的分析得出:在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; }
|