单片机 裸奔 模拟多任务调度模型 :消息队列 + 状态机 + 定时器

对于简单的嵌入式应用多数裸奔就能解决,但写出来的裸奔代码质量也由好坏之分。

在网上看到了这样一篇文字:
在这里插入图片描述
上面说到了裸奔环境下的多任务模型 - stateMachine + timerTick + Queue,也提到具体怎么做。

伪代码实现

//消息类型
enum MessageType {
    
    
	MSG_USART1,
	MSG_USART3,
	MSG_20MS = 20,
	MSG_100MS = 100,
};
typedef enum MessgeType enMsgType

stMsgQueue   g_AppMsgQueue;

void AppMsgHandle(enMsgType msg)
{
    
    
	switch (msg)
	{
    
    
		case MSG_USART1:
		{
    
    
			Usart1MsgHandle();
			break;
		}
		case MSG_USART3:      
		{
    
    
			Usart3MsgHandle();
			break;
		}
		case MSG_20MSG:        //定时20MS处理的任务
		{
    
    
			...
			break;
		}
		case MSG_100MS:       //定时100ms处理的任务
		{
    
    
			...
			break;
		}
	}
}

int main(void)
{
    
    
	Hardware_Init();
	
	enMsgType msg;
	
	while(1)
	{
    
    
		if (MQ_GetMsg(&g_AppMsgQueue, &msg))
			AppMsgHandle(msg);
	}
}


void USART1_IRQHandler(void)
{
    
    
	if (USART_GetTIFlag(USART1, TI_IDLE) == SET)   
	{
    
    
		MQ_PublishMsg(&g_AppMsgQueue, MSG_USART1);     //接收完一帧数据发送MSG_USART1消息给消息队列
	}
}

void USART3_IRQHandler(void)
{
    
    
	if (USART_GetTIFlag(USART3, TI_IDLE) == SET)
	{
    
    
		MQ_PublishMsg(&g_AppMsgQueue, MSG_USART3);  
	}
}


//1ms中断  timerTick
void TIM_IRQHandler(void)
{
    
    
	static uint16_t msCount = 0;
	
	if (TIM_GetTIFlag(TIM2, TI_UPDATE) == SET)
	{
    
    
		msCount++;
		
		if (msCount % MSG_20MS == 0)
			MQ_PublishMsg(&g_AppMsgQueue, MSG_20MS);  
	
		if (msCount % MSG_100MS == 0)
			MQ_PublishMsg(&g_AppMsgQueue, MSG_100MS);  
	}
}

由于使用的消息队列处理的任务,消息队列可以缓存事件,即使其中一个任务处理事件过长,其他任务事件也不会丢失。

对于紧急处理的任务可以将消息插入队头:

MQ_PublishArgentMsg(&g_AppMsgQueue, MSG_USART1); 

stateMachine + timerTick + Queue已经应用到实际项目中,确实好用。

仔细想想,其实很多系统啥的事件都是使用的消息队列处理的事件。

猜你喜欢

转载自blog.csdn.net/qq_36413982/article/details/112337880