STM32F407ZGT6-UCOSIII笔记11:任务内建消息队列

news/2024/12/21 2:32:44/

任务内建消息队列简化了外部定义的代码,而且也比外部消息队列更有效

 本文学习与程序编写基于 正点原子的 STM32F1 UCOS开发手册

文章提供测试代码讲解、完整工程下载、测试效果图

这次设计的实验在启动方面  还是有瑕疵的,但不影响观察效果:  

 

目录

任务内建消息队列:

创建任务内建消息队列:

 实验目标解释:

 目前各个文件任务:

#include "main.h"

#include "Public.h"

#include "ComTask.h"

 #include "MessageTask.h"

 #include "CalculateTask.h"

测试效果截图: 

 测试工程下载:

 遇到的问题记录:


 

任务内建消息队列:

创建任务内建消息队列:

首先在#include "Public.h" 定义任务内建消息队列长度:

#define TASK_Q_NUM 4 //任务内建消息队列长度

然后在 #include "main.h" 的 void start_task(void *p_arg)

函数初始化任务的时候,设定内建消息队列大小:

 

 实验目标解释:

外部中断PA15 按键 用于给标志信号 让Comtask 开启关闭 软件定时器

但实际还是添加了一个标志位来防止ComTask打印频繁而扰乱观察:(手动关闭Comtask的打印提示)

//外部中断0服务程序
void EXTI15_10_IRQHandler(void)
{OS_Timer1_Periodic_flag=1;   // 定时器状态 标志取1 EXTI15_10_IRQ_flag=!EXTI15_10_IRQ_flag; //外部中断标志取反EXTI_ClearITPendingBit(EXTI_Line15); //清除LINE0上的中断标志位 
}	

 

 目前各个文件任务:

 

#include "main.h"

初始化各个任务,注释掉了本实验用不到的信号量、互斥信号量的初始化

这里没有别的初始化,就是需要注意一下开启了任务MessageTask的任务内建消息队列:

需要在初始化的时候定义消息长度:

#include "main.h"void start_task(void *p_arg);//开始任务函数int main(void)
{OS_ERR err;CPU_SR_ALLOC();Init_ALL();OSInit(&err);		//初始化UCOSIIIOS_CRITICAL_ENTER();//进入临界区//创建开始任务OSTaskCreate((OS_TCB 	* )&StartTaskTCB,		//任务控制块(CPU_CHAR	* )"start task", 		//任务名字(OS_TASK_PTR )start_task, 			//任务函数(void		* )0,					//传递给任务函数的参数(OS_PRIO	  )START_TASK_PRIO,     //任务优先级(CPU_STK   * )&START_TASK_STK[0],	//任务堆栈基地址(CPU_STK_SIZE)START_STK_SIZE/10,	//任务堆栈深度限位(CPU_STK_SIZE)START_STK_SIZE,		//任务堆栈大小(OS_MSG_QTY  )0,					//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息(OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,(void   	* )0,					//用户补充的存储区(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项(OS_ERR 	* )&err);				//存放该函数错误时的返回值OS_CRITICAL_EXIT();	//退出临界区	 OSStart(&err);  //开启UCOSIIIwhile(1);
}//开始任务函数
void start_task(void *p_arg)
{OS_ERR err;CPU_SR_ALLOC();p_arg = p_arg;CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset();	
#endif#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif		//初始化 OS_Timer1_Periodic 软件定时器OSTmrCreate((OS_TMR *) &OS_Timer1_Periodic ,   //OS系统 软件定时器 1 周期模式 (CPU_CHAR *) "OS_Timer1_Periodic", //定时器名称(OS_TICK ) 100,  // 启动延时 为100*10 ms(OS_TICK ) 20,   // 周期为 20*10 ms(OS_OPT  ) OS_OPT_TMR_PERIODIC, //周期定时模式(OS_TMR_CALLBACK_PTR ) OS_Timer1_Periodic_callback,//回调函数(void * )  0,//参数为0(OS_ERR *) &err		);OS_CRITICAL_ENTER();	//进入临界区创建消息队列 Message_Msg 							
//	OSQCreate( (OS_Q *) &Message_Msg,//消息队列 Message_Msg
//						 (CPU_CHAR	* )"Message_Msg", //名称
//						 (OS_MSG_QTY ) Message_Msg_NUM, //消息队列长度
//						 (OS_ERR *)	 &err   
//							);
创建消息队列 DATA_Msg							
//	OSQCreate( (OS_Q *) &DATA_Msg,//消息队列 DATA_Msg
//						 (CPU_CHAR	* )"DATA_Msg", //名称
//						 (OS_MSG_QTY ) DATA_Msg_NUM, //消息队列长度
//						 (OS_ERR *)	 &err   
//							);							//创建ComTask任务OSTaskCreate((OS_TCB 	* )&COMTASKTaskTCB,		(CPU_CHAR	* )"com task", 		(OS_TASK_PTR )comTask, 			(void		* )0,					(OS_PRIO	  )COMTASK_TASK_PRIO,     (CPU_STK   * )&COMTASK_TASK_STK[0],	(CPU_STK_SIZE)COMTASK_STK_SIZE/10,	(CPU_STK_SIZE)COMTASK_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					//之前为0 //2个时间片 2*5ms(void   	* )0,					(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR 	* )&err);				//创建MessageTask任务OSTaskCreate((OS_TCB 	* )&MessageTaskTaskTCB,		(CPU_CHAR	* )"Message task", 		(OS_TASK_PTR )MessageTask, 			(void		* )0,					(OS_PRIO	  )MessageTask_TASK_PRIO,     	(CPU_STK   * )&MessageTask_TASK_STK[0],	(CPU_STK_SIZE)MessageTask_STK_SIZE/10,	(CPU_STK_SIZE)MessageTask_STK_SIZE,		(OS_MSG_QTY  )TASK_Q_NUM,					(OS_TICK	  )0,					//之前为0 //2个时间片 2*5ms(void   	* )0,				(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR 	* )&err);//创建CalculateTask任务OSTaskCreate((OS_TCB 	* )&CalculateTaskTaskTCB,		(CPU_CHAR	* )"Calculate task", 		(OS_TASK_PTR )CalculateTask,	(void		* )0,					(OS_PRIO	  )CalculateTask_TASK_PRIO,     	(CPU_STK   * )&CalculateTask_TASK_STK[0],	(CPU_STK_SIZE)CalculateTask_STK_SIZE/10,	(CPU_STK_SIZE)CalculateTask_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					(void   	* )0,				(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR 	* )&err);				 //		//创建 Shared_Str共享全局资源 的 信号量							
//		OSSemCreate((OS_SEM *) &SEM_Shared_Str, //指向信号量
//								 (CPU_CHAR *) "SEM_Shared_Str", //信号量名称
//								  (	OS_SEM_CTR ) 1,     //信号量值为1
//								  (OS_ERR *)  &err
//								 );		
//								 
//		//创建 Shared_Str共享全局资源 的 互斥信号量							
//		OSMutexCreate((OS_MUTEX *) &MUTEX_Shared_Str, //指向互斥信号量
//								 (CPU_CHAR *) "MUTEX_Shared_Str", //互斥信号量名称
//								  (OS_ERR *)  &err
//								 );OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err);		//挂起开始任务			 OS_CRITICAL_EXIT();	//进入临界区
}

#include "Public.h"

软件定时器的回调函数, 软件定时器任务:打印运行提示信息,发送消息

如果有系统错误出现  “ 该错误在 本次实验一般是 消息队列空了,没法再发了 ”
就重置标志 OS_Timer1_Periodic_flag ,关闭定时器

软件定时器周期 200ms

// OS_Timer1_Periodic 定时器回调函数 
// 打印提示信息
void OS_Timer1_Periodic_callback(void *p_tmr,void *p_arg)
{OS_ERR err;char *pbuf="Timer1";static int Timer1_count=0;
//	CPU_SR_ALLOC();	Timer1_count++;//打印中断次数UsartPrintf(USART1, "OS_Timer1_Periodic Print %d\r\n",Timer1_count);//	OS_CRITICAL_ENTER();      //进入临界区
//	sprintf((char *)pbuf,"Timer1_count %d",Timer1_count);  //虽添加了临界段保护,但这里的sprintf没法正常拼接字符串
//	OS_CRITICAL_EXIT();	 				      //退出临界区			OSTaskQPost((OS_TCB *) &MessageTaskTaskTCB, //向 MessageTask 发送消息(void *) pbuf,(OS_MSG_SIZE ) 10,(OS_OPT ) OS_OPT_POST_FIFO,(OS_ERR *) &err );		//如果有系统错误出现 “该错误在 本次实验一般是 消息队列空了,没法再发了”//就重置标志,关闭定时器if( err != OS_ERR_NONE){OSTmrStop(&OS_Timer1_Periodic,OS_OPT_TMR_NONE,OS_Timer1_Periodic_callback,&err);//关闭OS_Timer1_Periodic定时器OS_Timer1_Periodic_flag=0; //重置标志位UsartPrintf(USART1, "OS_Timer1_Periodic Stop\r\n");	//打印 提示软件定时器停止了	}
}

 

#include "ComTask.h"

#include "ComTask.h"/*ComTask 打印系统节拍频率 删除CalculateTask ComTask 计数 自己运行次数根据外部中断 控制的 OS_Timer1_Periodic_flag 标志位来 开关软件定时器 并在这些操作之后打印自己运行次数 延时50ms
*/void comTask(void * p_arg)
{OS_ERR err;int i=0,OSTime_tickRate;p_arg = p_arg;OSTime_tickRate=OSCfg_TickRate_Hz;            //获取系统节拍频率,(该宏定义在 OS_CFG_APP.H)UsartPrintf(USART1, "OSCfg_TickRate_Hz = %d Hz \r\n",OSTime_tickRate);  //打印系统节拍频率OSTaskDel((OS_TCB*)&CalculateTaskTaskTCB,&err);      //删除CalculateTask UsartPrintf(USART1, "ComTask delete CalculateTask !\r\n");	//打印删除 CalculateTask 提示UsartPrintf(USART1, "ComTask Print %d\r\n",i);	//打印 ComTask 运行次数while (DEF_TRUE){i++;if(EXTI15_10_IRQ_flag==1){//根据外部中断 控制的 OS_Timer1_Periodic_flag 标志位来 开关软件定时器 if(OS_Timer1_Periodic_flag==1){OSTmrStart(&OS_Timer1_Periodic,&err); //开启OS_Timer1_Periodic定时器UsartPrintf(USART1, "ComTask Print %d\r\n",i);	      //打印 ComTask 运行次数UsartPrintf(USART1, "OS_Timer1_Periodic Start\r\n");	//打印 提示软件定时器开启了		}else if(OS_Timer1_Periodic_flag==0){OSTmrStop(&OS_Timer1_Periodic,OS_OPT_TMR_NONE,OS_Timer1_Periodic_callback,&err);//关闭OS_Timer1_Periodic定时器UsartPrintf(USART1, "ComTask Print %d\r\n",i);	    //打印 ComTask 运行次数}}OSTimeDlyHMSM(0,0,0,50,OS_OPT_TIME_HMSM_STRICT,&err); //延时50ms}}

 

 #include "MessageTask.h"

 

 

 #include "CalculateTask.h"

 本次实验此任务被删除,不做解释

 

测试效果截图: 

这次设计的实验在启动方面  还是有瑕疵的,但不影响观察效果:  

 按下按键Comtask打开定时器:

再按下按键定时器开始正常运行:

定时器运行9次消息量用完,就停止了:

MessageTask在 随后的时间内将剩余4次消息量用完也停止了:

 这是因为定时器200ms就发送一次消息队列,而MessageTask 400m才处理一次,这就导致了他们收发处理不对等,最终导致 定时器提前用完 消息队列将自己关闭了

 

 测试工程下载:

 工程包含一份程序设计框架说明,不明白可以看看:

 https://download.csdn.net/download/qq_64257614/90155716

 

 遇到的问题记录:

我定时器发送消息队列原本想用字符串拼接好的,让MessageTask打印,但发送的结果是乱码,不知道为何,还没解决......


http://www.ppmy.cn/news/1556798.html

相关文章

Docker安装及基本使用

介绍 Docker于2013年首次发布,由Docker, Inc开发。‌‌Docker是一种用于构建、发布及运行应用程序的开源项目,它基于操作系统层级的虚拟化技术,将软件与其依赖项打包为容器‌。Docker的核心概念是“容器”(Container)…

长沙家具叠影床,让生活浸染自由浪漫

在繁华都市的喧嚣中,长沙铂乐家具叠影床宛如一方宁静的港湾,悄然静卧于家居空间。它以独特的设计语言,诉说着自由与浪漫的故事。 汲取世间万物之美,实现人与家具的美好互动,铂乐家具叠影床以光影交错为灵感&#xff0…

el-tree组件的父节点半选中状态—(选中和不选中的区别)

一.不选中父节点 回显数据需要在el-tree组件添加default-checked-keys属性 <template><div><el-button type"primary" click"handleShowData">回显数据</el-button><el-tree :props"{ children: children, label: name …

图的基本概念|存储

图的基本概念 图的定义 图G由顶点集V和边集E组成&#xff0c;记为G&#xff08;V&#xff0c;E) 其中V(G)表示图G中顶点的有限非空集&#xff1b;E&#xff08;G)表示图G中顶点之间的关系&#xff08;边&#xff09;集合。 若V{ v 1 , v 2 , … , v n v_{1},v_{2},\dots,v_{n…

Linux下调试工具:gdb

Windows和Linux下的调试有区别吗&#xff1f; 调试思路上一定是一样的&#xff1b;调试的操作方式有差别(Linux命令行调试&#xff0c;Windows窗口) 1.准备工作&#xff1a; 默认情况下&#xff0c;gdb无法进行对现在发布的程序进行调试(debug / release)。在Linux下用gcc编译…

repmgr集群部署-PostgreSQL高可用保证

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、My…

Kaggler日志--Day9

进度24/12/18 昨日复盘&#xff1a; 补充并解决Day7Kaggler日志–Day7统计的部分问题 今日进度&#xff1a; 继续完成Day8Kaggler日志–Day8统计问题的解答 明日规划&#xff1a; 今天报名了Regression with an Insurance Dataset算是新手村练习比赛&#xff0c;截止时间是2…

clearvoice 语音降噪、语音分离库

参看: https://github.com/modelscope/ClearerVoice-Studio/tree/main ClearVoice 提供了一个统一的推理平台,用于语音增强、语音分离以及视听目标说话人提取。 代码参看: https://github.com/modelscope/ClearerVoice-Studio/tree/main/clearvoice https://github.com/mode…