嵌入式产品中有许多面板式按键(Adhesive Keypad),下面的原代码演示如何在ZRTOS中使用驱动器来实现面板式按键。
1、问题综述
在本例中有5个按键,它们分别是MENU,UP,DOWN,SELECT, and PRINT. 键的输入信号被分别被引入到A/D入口,当键未被按下时,入口为高电位,一但键被按下,入口转为低电位。以下是部分原代码:
#define _KEY_ALL_RELEASED (0)
#define _KEY_MENU (1)
#define _KEY_PRINT (2)
#define _KEY_SELECT (3)
#define _KEY_DOWN (4)
#define _KEY_UP (5)
#define _KEY_BD_CHECK_INTERVAL (20) //refuse to take the same key press
//within 20 tick or 200ms
#define _KEY_BD_TIME_2_LIVE ((U8) 250)//if a menu item was not selected in 250
//tick or 2500ms, the action will be
//canceled
static U8 time_out; //time out timer
static U8 key_status; //key status, either pressed or release
static long timer = _KEY_BD_CHECK_INTERVAL*3; //time out timer
void key_bd_Init(void) //keypad initialization
{
//...
rtos_taskSpawn(RTOS_PEND_FOREVER_PRI-4, (RTOS_FUNCPTR) key_bd_task, 0); //
//spawn a task to handle keypad input
timer = _KEY_BD_SELECTED_INTERVAL;
sem = rtos_semBCreate(0, SEM_EMPTY); //create a semaphone to inform the task
//key_bd_task
//...
key_status = _KEY_ALL_RELEASED;
}
//
static int get_key_bd_data(U16 fd, U8 key) //get input from keypad
{ //fd - file descriptor of device driver of a key
//key - the key to be detected
U16 data[2];//data to read;
if (read(open(fd), (char*) data, 2) > 0) { //read data from fd
//the data is available
if (data[0]) { //the key is pressed
if (key_status == _KEY_ALL_RELEASED) { //the key is freshly pressed
time_out = _KEY_BD_TIME_2_LIVE; //set a time out time
key_status = key; //set the key status to "this key was pressed"
return TRUE; //return action flag
}
} else { //data is released
if (key == key_status) { //this key used to be pressed, now released
key_status = _KEY_ALL_RELEASED;//set the key status as released
}
}
return 0;//return action flag
}
return ERROR; //there is no data in this device driver
}
//
static void key_bd_task(void) //periodic task with a priod of "timer"
//the task to handle keypad press
{
int delta;
long result = rtos_semTake(sem, timer);//try to get the semaphone with a timeout
if (result == (long) OK) return; //this is not a time out, do nothing
//it is a time out
//...
timer = _KEY_BD_CHECK_INTERVAL;//reset the timeout timer
if (time_out != (U8) 255 && time_out) {
time_out--; //decremental the time out timer, as a menu item was not selected
//if time_out == 0, the action will be canceled
}
delta = get_key_bd_data(SOS_INPUT_BUTTON, _KEY_MENU); //check key "MENU"
if (delta > 0) { //"MENU" key is pressed
//...
} else if (delta < 0) goto _out; //the device driver not ready, why ? think about
if (get_key_bd_data(PRNT_INPUT_BUTTON, _KEY_PRINT)) {//check key "PRINT"
//the key "PRINT" pressed
//...
} else
if (get_key_bd_data(SLCT_INPUT_BUTTON, _KEY_SELECT)) {//check key "SELECT"
//the key "SELECT" pressed
//...
} else
if (get_key_bd_data(DNW_INPUT_BUTTON, _KEY_DOWN)) {//check key "DOWN"
//the key "DOWN" pressed
//...
} else
if (get_key_bd_data(UP_INPUT_BUTTON, _KEY_UP)) { //check key "UP"
//the key "UP" pressed
//...
}
_out:
if (time_out == 0) {
init_kd(); //cancel the action
}
}
2、结论
在上述代码中,任务的周期由时钟“timer”确定。设计者即可以用rtos_taskDelay()也可以用rtos_semTake()来实现。
文章评论(0条评论)
登录后参与讨论