wuzhixuan 发表于 2024-5-8 16:49:09

ADC分压按键代码,有大佬教教小白马

同一个adc io口,通过adc值不同检测 s1,s2,s3,ADC分压按键 s1(开关),s2(增加温度),s3(减温度),长按s2连续增加,长按s3连续减少,s2和s3一起长按切换华氏度,或者摄氏度,目前只是做了按一次,但是长按会有问题 ,大佬们有比较优秀的代码让我学习学习吗

wuzhixuan 发表于 2024-5-8 17:00:32

基础大佬提供的扫描方法,优化的。请大佬指教一下,好像哪里还有问题,菜鸟自己看不出

本帖最后由 wuzhixuan 于 2024-5-15 11:04 编辑


void KeyScan(void){
    static unsigned char ADC_sap_cont, key_last, key_release;
    unsigned char key_th;
    adcData = GET_ADC_DATA(4);// 通道4 AD值
    theVoltage = (unlong) adcData * 5 * 100 / 4096;    //电压放大100倍

    if (100 < theVoltage) {
      if (theVoltage >= 450) { key_th = 1; }          // S2 开关 按键
      else if ((theVoltage <= 340) && (theVoltage >= 290)) { key_th = 2; } // S3 - 按键
      else if ((theVoltage <= 250) && (theVoltage >= 220)) { key_th = 3; } // S4 + 按键
      else if ((theVoltage <= 390) && (theVoltage >= 350)) { key_th = 4; } // S3+S4 同时按下按键
      else { key_th = 0; }
      if (key_last == key_th) { ADC_sap_cont++; }          //键值稳定后开始累计
      else { key_last = key_th, ADC_sap_cont = 0; }          //不稳定键值将被替换抛弃

      if (ADC_sap_cont >= 200)                                                //如果键值稳定且累计成功
      {
            key_release = 1;
            Key_value = key_last;
      }
    } else {
      if (key_release == 1) {
            key_release = 0;
            if (key_flag == 0)                                              //并且当前无未处理键值
            {
                ADC_sap_cont = 0;                                           //则输出键值

                key_flag = 1;
            } else { ADC_sap_cont = 200; }                                  //如果有未处理键值,则等待

      }
      ADC_sap_cont = 0;
    }
}
void keyAction() {
    if (key_flag) {// 检查是否有未处理的键值
      switch (Key_value) {
            case 1:
                toggle_power();// 切换电源开关
                break;
            case 2:
                decrease_temperature();// 减少温度
                break;
            case 3:
                increase_temperature();// 增加温度
                break;
            case 4:
                switch_temperature_unit();// 切换温度单位
                break;
            default:
                // 无操作
                break;
      }
      key_flag = 0; // 处理完毕后重置key_flag
    }

    Key_value = 0; // 执行完任务后将Key_value清零
}

wuzhixuan 发表于 2024-5-8 17:01:37

wuzhixuan 发表于 2024-5-8 17:00


代码是这样的,感觉有问题,而且实际测量的电压值和计算的电压值相差很大,大佬可以帮忙优化一下吗

晓飛飛 发表于 2024-5-8 18:37:34

我常用的ADC按键代码,你可以参考一下,已经批量在产品上应用,比较稳定的。
void ADC0_ISR (void) interrupt 5
{
    static unsigned char ADC_sap_cont,key_last,key_release;
      unsigned char key_th;      
      ADC_CONTR &= ~0x20;                //清ADC中断标记
      key_adc = (unsigned int)ADC_RES<<8 | ADC_RESL;         //取AD值

      if(key_adc<2100)
      {
                if                (key_adc<200)                                                 {key_th = 1;}      //键值分段,实际测试得到区间
                else if ((key_adc<700) && (key_adc>=200))         {key_th = 2;}
                else if ((key_adc<1100) && (key_adc>=700))         {key_th = 3;}
                else if ((key_adc<2100) && (key_adc>=1100))      {key_th = 4;}
                else                                                                              {key_th = 0;}
                if (key_last == key_th)      {ADC_sap_cont++;}          //键值稳定后开始累计
                else{key_last = key_th,ADC_sap_cont=0;}          //不稳定键值将被替换抛弃

                if(ADC_sap_cont>=200)                                                //如果键值稳定且累计成功
                {
                        key_release = 1;
                        key_valu = key_last;
                }
      }
      else                                                                                       //如果无按键,则及时清零
      {
                if(key_release == 1)
                {
                        key_release = 0;
                        if(key_flag == 0)                                                //并且当前无未处理键值
                        {
                              ADC_sap_cont = 0;                                          //则输出键值
                              
                              key_flag = 1;
                        }
                        else {ADC_sap_cont = 200;}                                  //如果有未处理键值,则等待
      
                }
                ADC_sap_cont = 0;
      }
      ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | 0x00;    //再次启动 AD 转换                           
}



wuzhixuan 发表于 2024-5-8 23:49:43

晓飛飛 发表于 2024-5-8 18:37
我常用的ADC按键代码,你可以参考一下,已经批量在产品上应用,比较稳定的。




谢谢大佬

wuzhixuan 发表于 2024-5-9 00:09:23

晓飛飛 发表于 2024-5-8 18:37
我常用的ADC按键代码,你可以参考一下,已经批量在产品上应用,比较稳定的。




大佬,你这个代码就很简洁很精妙

wuzhixuan 发表于 2024-5-9 00:16:41

晓飛飛 发表于 2024-5-8 18:37
我常用的ADC按键代码,你可以参考一下,已经批量在产品上应用,比较稳定的。




if (key_flag == 0) //并且当前无未处理键值这快代码不是很明白,可以帮忙讲解一下吗,还有就是 key_valu = key_last; 为啥是等于上一次的值,不等于key_th

晓飛飛 发表于 2024-5-9 01:21:15

wuzhixuan 发表于 2024-5-9 00:16
if (key_flag == 0) //并且当前无未处理键值这快代码不是很明白,可以帮忙讲解一下吗,还有就是 key_va ...

是一种消抖措施

wuzhixuan 发表于 2024-5-9 01:40:16

晓飛飛 发表于 2024-5-9 01:21
是一种消抖措施

大佬,这个好像不支持长按和两个按键同时按,长按s3,长按s4,已经s3,s4同时按

晓飛飛 发表于 2024-5-9 08:43:47

wuzhixuan 发表于 2024-5-9 01:40
大佬,这个好像不支持长按和两个按键同时按,长按s3,长按s4,已经s3,s4同时按
...

长按、双击这些都可以在这个代码基础上进行扩展,需要额外增加代码实现的。
页: [1] 2 3
查看完整版本: ADC分压按键代码,有大佬教教小白马