一.MTK按键扫描原理:
不同的MTK平台内部提供的按键数目各有不同,但是扫描原理大致一样,这里以MTK6253为例来讲解记录。
MTK提供6*7共42个矩阵键盘,加上Power键总共43个按键,其中BB芯片引出6根行线ROW,7根列线COL,如下图。
下面来说明一下扫描原理:
在初始化或是没有按键的情况下,ROW设置为输出,COL设置为输入。
BB芯片的内部设有一个按键中断,在没有任何按键的情况下,所有CLO线为高电平,ROW线为低电平,一旦有按键按下,比如key10(ROW1,COL2)有按下,由于COL2线与ROW1线直接相连,COL2线即被拉低,只要COL线有被拉低的,内部按键中断便会响应,内部按键中断产生后,BB就知道有按键产生,这时就进行按键扫描,判断出事哪个按键按下,然后进行相应的处理。
中断产生后,BB先发出消息将所有COL线置高,所有ROW线置低,扫描COL线,比如key10(ROW1,COL2)有按下,会扫描到COL2被拉低;再将将所有ROW线置高,所有COL线置低,扫描ROW线,比如key10(ROW1,COL2)有按下,会扫描到ROW1被拉低;那么COL2和ROW1组合起来就知道哪个按键按下了。
但是实际上按键中断产生后,扫描过程已经在BB内部迅速完成,然后把相应的按键位置用寄存器保存起来。
每个寄存器16位,每一位代表一个按键,那么总共53个按键,需要4个寄存器去保存。按键的对应位置如下图:
寄存器的每个位对应一个按键,默认为1,当有按键按下,那么相应位置0。然后系统去读这四个寄存器,就能知道是哪一个按键按下。
读取代码如下:
#if defined(DRV_KBD_32KEYS_ABOVE)
kbd_map_temp_reg1 = (kal_uint32)(DRV_Reg(KP_HI_KEY));
#elif defined(DRV_KBD_48KEYS_ABOVE)
kbd_map_temp_reg1 = ( ((kal_uint32)(DRV_Reg(KP_HI_KEY) << 16))|((kal_uint32)(DRV_Reg(KP_MID1_KEY))) );
#elif defined(DRV_KBD_64KEYS_ABOVE)
kbd_map_temp_reg1 = ( ((kal_uint32)(DRV_Reg(KP_MID2_KEY) << 16))|((kal_uint32)(DRV_Reg(KP_MID1_KEY))) );
kbd_map_temp_reg2 = (kal_uint32)(DRV_Reg(KP_HI_KEY));
#endif
二.代码部分:
按键扫描代码在kbdmain.c文件中的kbd_task_main函数。上层MMI处理在keybrd.c文件里。
首先,在Kbd_Init初始化时注册按键中断
DRV_Register_HISR(DRV_KP_HISR_ID, Kbd_HisrEntry);
其次,一旦有按键产生,那么在中断处理函数里面发送一个按键事件,在kbd_task_main函数里会有一个死循环一直不停的扫描这个按键时间,若没有按键事件发生,那么就退出此次循环(continue),一旦检测到有按键事件发生,便开始读取寄存器中的值并进行相关处理。
{
#ifdef KEY_DEBUG
dbg_print("Kbd_HisrEntry\r\n");
#endif
#if defined(__EXTEND_QWERTY_KEYPAD__)
//use gpt polling instead of key IRQ event trigger
IRQMask(IRQ_KPAD_CODE);
#endif //#if defined(__EXTEND_QWERTY_KEYPAD__)
KBD_DBG(__LINE__, KBD_GetTimeStamp(), ust_get_current_time(),0);
/*lint -e(534)*/kal_set_eg_events(KBD.event,1,KAL_OR); //设置按键事件
}
在kbd_task_main函数中检查按键事件
continue;
最后,将按键时间发送到MMI层进行处理。
另外附加补充一下:
如果是全键盘的话,NEOTEL53_09B_GPRS.mak中的KEYPAD_TYPE=QWERTY_KEYPAD。如果有扩展按键的话(即用地或GPIO口模拟ROW线来扩展按键)=KEYPAD_TYPE=EXTEND_QWERTY_KEYPAD