在项目里面,有些工程师习惯,在定时器服务程序里面,置标志,然后在主程序里面去检查标志,如果标志被置,则去执行一些操作,这样的做法,如果项目很简单,是demo,可以这样做,因为速度快。
如果项目有些小规模,不建议这样使用,因为这样会导致全局变量多,管理全局变量有些费事。建议定义一个状态,使用不同的事件去处理。
例如:
typedef enum
{
eKeySelect = 0, //选择按键事件
eKeyConfirm, //确认按键事件
eBatChargeIng, //电池标充电进行事件
eOperateFinish, //电池充电完成事件, 电池修护完成事件, 电容充电完成事件
eBatInfo, //查看电池信息事件
eErrFaultCode, //故障代码
}DispTaskEvent_t;
uint32_t GET_EVENT(void)
{
uint32_t tmp_event = g_fsm_disp_event;
g_fsm_disp_event = 0;
return tmp_event;
}
/*
设置事件,是设置总事件的某一位。
读取事件,将事件读取后,要将该事件位清除,表示已处理掉该位的事件。
*/
void SET_EVENT(uint32_t event_id)
{
g_fsm_disp_event |= BIT(event_id);
}
/*
清除事件,清除总事件的某一位。
*/
void CRC_EVENT(uint32_t event_id)
{
g_fsm_disp_event &= ~BIT(event_id);
}
void scan_key(void)
{
if(!KEY_SELECT)
{
HAL_Delay(10);
if(!KEY_SELECT)
{
while(!KEY_SELECT);
SET_EVENT( eKeySelect); //给显示流程设置选择按键操作事件
}
}
if(!KEY_CONFIRM)
{
HAL_Delay(10);
if(!KEY_CONFIRM)
{
while(!KEY_CONFIRM);
SET_EVENT( eKeyConfirm ); //给显示流程设置选择按键操作事件
}
}
}
/*命令解析*/
void analyze_comm_data(DEVICE_STATE *pDevice_State, uint8_t Size)
{
uint8_t tmp_work_state = 0;
uint16_t tmp_abnormal = 0;
if((0 == pDevice_State) || (0 == Size))
{
return;
}
tmp_work_state = pDevice_State->cmd;
tmp_abnormal = pDevice_State->abnormal_code;
/*根据工作状态切换主状态机*/
switch(tmp_work_state)
{
case CMD_STATE_BATTERY_CHARGE:
SET_EVENT(eBatChargeIng);
break;
case CMD_STATE_OPERATE_FINISH:
SET_EVENT(eOperateFinish);
break;
case CMD_STATE_INFO: //根据收到的帧数据中,设备类型切换到不同的状态。
SET_EVENT(eBatInfo);
break;
case CMD_STATE_ABNORMAL:
SET_EVENT(eErrFaultCode);
setFault(tmp_abnormal);
break;
default:
break;
}
}
if(checkEventID(tmp_event, eKeySelect))
{
g_disp_fsm_para.l_fsm_disp_state = STATE_SELECT_2;
return; //每次一个状态下,只能处理一个事件,处理完此事件后,要把事件清0,否则有可能处理多次事件,引起逻辑错误。
}
if(checkEventID(tmp_event, eKeyConfirm))
{
OLED_Clear();
g_disp_fsm_para.l_fsm_disp_state = STATE_BATTERY_CHARGE;
return;
}