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

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

在网上看到了这样一篇文字:
在这里插入图片描述
上面说到了裸奔环境下的多任务模型 - 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已经应用到实际项目中,确实好用。

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

  • 5
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欲盖弥彰1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值