lxj19901115的个人空间 https://bbs.21ic.com/?754113 [收藏] [复制] [RSS]

日志

关于AD扫键

已有 583 次阅读2014-12-27 22:46 |个人分类:备份|系统分类:单片机| 程序, 动态, 信息

不管是IO扫键,还是AD扫键,其核心点是在有按键的时候,状态会发生变化,所以在写扫键的时候,基本上都会使用状态机机制
显而易见的是这四个状态分别为
c_ADC_Key_Status_IDLE  空闲状态
c_ADC_Key_Status_DB 消抖
c_ADC_Key_Status_PressDown 确认按键按下
c_ADC_Key_Status_PressUp  确认按键松开
另外,在扫AD按键的时候,都有AD值,所以推荐针对不同的AD值的时候,应该做一个对于该AD值的按键掩码
这样做的好处有,可以根据不同的掩码值,来设置该按键的不同信息,和索引值,、
然后根据索引值来建立一个表格,
故在确认按键状态的时候,可以根据索引去动态的修改,这样程序的可维护性和健壮性会大大的加强,
具体AD扫键代码和思维如下
/*
描述:
        AD扫键,使用状态机机制
作者:GHOUL


*/
#include "adc_key.h"


u8 g_adc_key_buffer;                                        //AD缓存寄存器
u8 g_adc_key_status;                                        //AD扫键状态标记
u8 g_Flag_adc_timer;                                        //AD扫描定时器标志,外部使用64HZ
u8 g_adc_DBtimerCnt;                                        //消抖计数
u8 g_adc_hold_keyTimerCnt;                                //用于长按计数
/*
  函数名字:ADC_Key_Init
  形参:无
  返回:无
  功能:AD按键初始化
*/
void ADC_Key_Init(void)
{
        ADC_ChannelInit();                                                                                        //AD寄存器初始化
        g_adc_key_status = c_ADC_Key_Status_IDLE;                                        //设置扫键初始状态
        g_adc_key_buffer = 0;                                                                                //设置缓冲器
        g_adc_DBtimerCnt = 0;
        g_adc_hold_keyTimerCnt = 0;
}
/*
  函数名字:ADC_ChannelGetKeyIdx
  形参:无
  返回:u32 按键索引值
  功能:根据读取到的AD值,计算按键在表格中的索引值
*/
static u32 ADC_ChannelGetKeyIdx(void)
{
        u16 t_adc_value;
        u8 t_adc_value_idx;
        t_adc_value = ADC_GetValue();                                                                                                                                                                //读取AD值
                                                                                                                                                                                                                                //根据AD值,得出该按键在键值索引表中的位置
        if(t_adc_value >= (c_AD_Accuracy_Value - (c_AD_Accuracy_Value / c_AD_Key_Num) / 2))
        {
                return c_Key_Null;
        }
        t_adc_value_idx = (Val + (c_AD_Accuracy_Value / c_AD_Key_Num) / 2) * c_AD_Key_Num / c_AD_Accuracy_Value + 1;
                                                                                                                                                                                                                                //返回索引值
        return t_adc_value_idx;
}
/*
  函数名字:ADC_Key_GetIdx
  形参:无
  返回:u16 按键索引值
  功能:根据读取到的AD值,计算按键在表格中的索引值,并确认状态
*/
u16 ADC_Key_GetIdx(void)
{
        u8 tw_adc_key_idx;
        if(!g_Flag_adc_timer)                                                                                        //定时器标志判断
        {
                return c_Key_Null;
        }
        g_Flag_adc_timer = c_Clear;                                                                                //释放定时器标志
        tw_adc_key_idx = ADC_ChannelGetKeyIdx();                                                //获取索引值
        switch(g_adc_key_status)
        {
                case c_ADC_Key_Status_IDLE:                                                                        //AD接口空闲状态
                {
                        if(tw_adc_key_idx == c_Key_Null)                                                //无按键
                        {
                                return c_Key_Null;
                        }
                        else
                        {
                                g_adc_key_buffer = tw_adc_key_idx;                                        //保存临时键值
                                g_adc_key_status = c_ADC_Key_Status_DB;                                //键值发生变化,进入消抖过程
                                g_adc_DBtimerCnt = c_AD_Key_DB;                                                //设置消抖时间
                        }
                }
                break;
                case c_ADC_Key_Status_DB:                                                                        //消抖过程
                {
                        if(g_adc_key_buffer != tw_adc_key_idx)                                        //键值发生变化从新扫描
                        {
                                g_adc_key_status = c_ADC_Key_Status_IDLE;
                                return c_Key_Null;
                        }
                        else
                        {
                                g_adc_DBtimerCnt--                                                                        //未变化,继续消抖
                                if(g_adc_DBtimerCnt < 1)
                                {
                                        g_adc_key_status = c_ADC_Key_Status_PressDown;        //消抖时间到,进入按键确认状态
                                }
                        }
                       
                }
                break;
                case c_ADC_Key_Status_PressDown:
                {
                        if(g_adc_key_buffer != tw_adc_key_idx)                                        //获取当前按键
                        {
                                g_adc_key_status = c_ADC_Key_Status_IDLE;
                                return (g_adc_key_buffer | KEY_STAT_PRESS);
                        }
                        else
                        {
                                g_adc_key_status = c_ADC_Key_Status_PressUp;                 //保持状态,说明进入长按模式
                                return (g_adc_key_buffer | KEY_STAT_LPRESS_DOWN);
                        }
                }

                case c_ADC_Key_Status_PressUp:
                {
                        if(g_adc_key_buffer != tw_adc_key_idx)                                        //在进入长安模式下,变化,说明按键松开
                        {
                                g_adc_key_status = c_ADC_Key_Status_IDLE;
                                return (g_adc_key_buffer | KEY_STAT_LPRESS_UP);
                        }
                        else
                        {
                                g_adc_key_status = c_ADC_Key_Status_PressUp;
                                return (g_adc_key_buffer | KEY_STAT_LPRESS_CONTINUE);//按键长按状态确认
                        }
                }

                default:
                {
                        g_adc_key_status = c_ADC_Key_Status_IDLE;                                //保留值,进入初始化状态
                }
                break;
        }
        return c_Key_Null;
}
/*
  函数名字:ADC_Key_GetIdx
  形参:无
  返回:u16 按键索引值
  功能:根据索引值,确认按键,并且返回按键状态
*/
u16 ADC_Key_Get(void)
{
        u16 tw_key_msg;
        u8 tw_keyIdx = ADC_Key_GetIdx();
        if(c_Key_Null == tw_keyIdx)                                                                        //无按键返回0
        {
                return 0;
        }
        else
        {
                tw_key_msg = T_ADC_Key_Map[tw_keyIdx &~ 0xf000];                //根据索引值,返回按键键值和按键状态
                return tw_key_msg;
        }
}

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)