一、事件系统
中断不能执行太过复杂的工作,可以设置一个事件标志,来让主循环和事件处理程序执行繁重的工作,事件处理循环将采用异步方式处置这个标志。
二、事件句柄
声明事件句柄的类型
typedef uint8_t EVNT_Handle;
列出将要使用的不同事件
/*<系统初始化事件>*/
#define EVNT_INT 0
/*!<事件1 : SW1 按下 */
#define EVNT_SW1_PRESSED 1
/*!<事件1 : SW2 按下 */
#define EVNT_SW2_PRESSED 2
/*!<事件1 : SW3 按下 */
#define EVNT_SW3_PRESSED 3
/*!<事件1 : SW4 按下 */
#define EVNT_SW4_PRESSED 4
/*!<哨兵事件数 */
#define EVNT_SW5_PRESSED 5
事件分时间片执行,可采用枚举类型进行定义
typedef enum {
EVNT_INIT, /* !, 系统初始化事件 */
EVNT_SW1_PRESSED, /*!<事件1 : SW1 按下 */
EVNT_SW2_PRESSED, /*!<事件2 : SW2 按下 */
EVNT_SW3_PRESSED, /*!<事件3 : SW3 按下 */
EVNT_SW4_PRESSED, /*!<事件4 : SW4 按下 */
EVNT_NOF_EVENTS, /*!<哨兵事件数 : 不同事件的数目 */
}EVENT_Handle;
三、事件方法
/* !
** \设置一个事件
** \param[in]事件,设置事件处理
*/
void EVNT_SetEvent(EVENT_Handle event);
/* !
** \清除一个事件
** \param[in]事件,清除事件处理
*/
void EVNT_ClearEvent(EVENT_Handle event);
/* !
** \返回一个事件的状态
** \param[in]事件,检查事件的事件处理
** \如果设置了事件,返回TRUE,否则返回FALSE
*/
void EVNT_GetEvent(EVENT_Handle event);
/* !
** \程序检查是否一个事件挂起
** \如果一个事件挂起,事件被清除并且调用回调函数
** \param[in]调用回调函数。
** \事件句柄传送给回调函数
*/
void EVNT_HandleEvent(void( * callback)(EVNT_Handle));
/* ! \事件模型初始化 */
void EVNT_Init(void);
四、事件数据结构
EVNT_SetEvent(EVENT_Handle event){
EVNT_Event[event/8] |= 0x80>>(event % 8);
}
void EVNT_ClearEvent(EVENT_Handle event){
EVNT_Event[event/8]&= ~(0x80>>(event % 8));
}
EVNT_GetEvent(EVENT_Handle event){
return (bool)(EVNT_Events[(event)/8]&(0x80>>((event)%8)));
}
五、事件处理
void EVNT_HandleEvent(void (* callback)(EVNT_Handle)) {
/* 处理一个具有最高优先级的事件,0表示最高的优先级 */
uint8_t event;
EnterCritical();
for(event = 0; event < EVNT_NOF_EVENTS; event++){
if(EVNT_GetEvent(event)){ /* 当前的事件? */
EVNT_ClearEvent(event); /*清除事件 */
break; /*退出循环*/
}
}
ExitCritical();
if(event != EVNT_NOF_EVENTS) {
callback(event)
}
}
六、集成
void main(void)
{
EVNT_SetEvent(EVNT_INIT);
for(;;){
EVNT_HandleEvent(APP_HandleEvent);
}
}
用EVNT_HandleEvent()函数传送一个额外的回调函数指针 APP_HandleEvent
void APP_HandleEvent(EVENT_Handle){
switch(event){
case EVNT_INIT:
break;
case EVNT_SW1_PRESSED:
/* user code*/
break;
case EVNT_SW2_PRESSED:
/* user code*/
break;
}
}
void interrupt KeyISR(void)
{
ACK_KBI_INTERRUPT(); /* 确认中断*/
if(Key1Pressed()){
EVNT_SetEvent(EVNT_SW1_PRESSED);
}
else if(Key2Pressed()){
EVNT_SetEvent(EVNT_SW2_PRESSED);
}
}
网友评论