说明
master的电视芯片V39的按键处理分析
不同的按键按下去读到不同的ad值,反过来根据按键值就可以得出是哪个按键。
ad值有一定范围。程序里一般是该值的容忍度,认为只要在容忍度范围内就是这个按键的值。
过程为为检测到按下 开始记录 检测到抬起后,检测记录的按键值是否一样。
探测到按键值后,全局标记g_bKeyDetect会被置位,handler处理函数处理后再清零。这就像生产者和消费者。
按键产生函数有BUG,可能产生串键。看着改吧
具体说明
1. AD值集合
下面代码是按键会触发的AD值集合。
BYTE code tADCKeyLevel[ADC_KEY_CHANNEL_NUM][8] =
{
{KEY1_AD_L0,KEY1_AD_L1,KEY1_AD_L2,KEY1_AD_L3,KEY1_AD_L4,KEY1_AD_L5,KEY1_AD_L6,KEY1_AD_L7},
{KEY2_AD_L0,KEY2_AD_L1,KEY2_AD_L2,KEY2_AD_L3,KEY2_AD_L4,KEY2_AD_L5,KEY2_AD_L6,KEY2_AD_L7},
};
如
#define KEY1_AD_L0 0x01
#define KEY1_AD_L1 0x26
#define KEY1_AD_L2 0x4D
#define KEY1_AD_L3 0x74
#define KEY1_AD_L4 0x9B
#define KEY1_AD_L5 0xB9
#define KEY1_AD_L6 0xD8
#define KEY1_AD_L7 0xEF
2. AD值的容忍度
#define KEY_AD_DELTA 0x05 // tolerance
3. AD值的获取
if (ucAdcLv < (tADCKeyLevel[ucAdcChannel][0] + KEY_AD_DELTA))
return tADCKeyLevel[ucAdcChannel][0];
else if ((tADCKeyLevel[ucAdcChannel][1]-KEY_AD_DELTA) < ucAdcLv && ucAdcLv < (tADCKeyLevel[ucAdcChannel][1]+KEY_AD_DELTA))
return tADCKeyLevel[ucAdcChannel][1];
...
4. 将AD值转换为按键
if(KeyValue<=KEY1_AD_L0)
KeyStatus |= tADCKeyFlag[0][0];
else if(KeyValue<=KEY1_AD_L1)
KeyStatus |= tADCKeyFlag[0][1];
...
按键定义如下
#define ADC_KEY_1_L0_FLAG KEY_POWER
#define ADC_KEY_1_L1_FLAG KEY_DOWN
#define ADC_KEY_1_L2_FLAG KEY_UP
#define ADC_KEY_1_L3_FLAG KEY_RIGHT
#define ADC_KEY_1_L4_FLAG KEY_LEFT
#define ADC_KEY_1_L5_FLAG KEY_MENU
#define ADC_KEY_1_L6_FLAG KEY_SOURCE
#define ADC_KEY_1_L7_FLAG KEY_PIP
typedef enum _KeyScanType
{
KEY_NOTHING = 0x00,
KEY_MENU = _BIT0,
KEY_UP = _BIT1,
KEY_DOWN = _BIT2,
KEY_LEFT = _BIT3,
KEY_RIGHT = _BIT4,
KEY_SOURCE = _BIT5,
KEY_PIP = _BIT6,
KEY_POWER = _BIT7,
//KEY_RELOAD_EEPROM = _BIT1 | _BIT2 | _BIT7
} KeyScanType;
5. 按键产生函数
void keyDetectPoll(void)
{
KeyScanType ucStatusBff; // status buffer
if (g_ucKeyCounter == 0) // check counter
{
#if 0// KEY_USE_INTERRUPT
ucStatusBff = IsrKeyScanStatus(); // scan key status
#else
ucStatusBff = keyScanStatus(); // scan key status
#endif
if (ucStatusBff == g_LastKeyStatus) // match last
{
if (g_bKeyDetect) // check key busy
;
else if (g_LastKeyStatus) // check key pressed
{
if (g_KeyCode == g_LastKeyStatus) // check repeat
{
if (g_bKeyCheckRepeat) // need to repeat
{
if (g_bKey1stRepeat)
{
g_ucKeyDebounce++;
if (g_ucKeyDebounce==KEY_DEBOUNCE_REPEAT)
{
g_ucKeyDebounce = 0;
g_bKey1stRepeat = 0;
g_bKeyDetect = 1; // detect key
}
}
else
{
g_bKeyRepeat = 1;
g_ucKeyDebounce++;
if ((!g_bKeypad_FastRepeat && g_ucKeyDebounce==KEY_DEBOUNCE_REPEAT)
|| (g_bKeypad_FastRepeat && g_ucKeyDebounce==KEY_DEBOUNCE_FAST))
{
g_ucKeyDebounce = 0;
g_bKeyDetect = 1; // detect key
}
}
}
}
else // new key pressed
{
g_KeyCode = g_LastKeyStatus;
g_bKeyDetect = 1; // detect key
g_bKeyRepeat = 0;
g_bKey1stRepeat = 1;
g_bKeyCheckRepeat = 0;
g_ucKeyDebounce = 0;
g_bKeypad_FastRepeat = 0;
#if ENABLE_MEDIA
if(ucStatusBff == KEY_MENU)
g_bJPKeyEventFlag = 1;
#endif
}
}
else // no key pressed
{
g_KeyCode = KEY_NOTHING; // reset key code
}
}
else // different
{
g_LastKeyStatus = ucStatusBff; // refresh key status
g_bKeyRepeat = 0;
g_bKey1stRepeat = 1;
g_bKeyCheckRepeat = 0;
g_ucKeyDebounce = 0;
g_bKeypad_FastRepeat = 0;
#if ENABLE_MEDIA
if(ucStatusBff == KEY_MENU)
g_bJPKeyEventFlag =1;
#endif
}
g_ucKeyCounter = KEY_DEBOUNCE_TIME; // next time counter
}
}