STM32F407ZGT6-UCOSIII笔记9:任务内嵌信号量

发布于:2024-12-20 ⋅ 阅读:(75) ⋅ 点赞:(0)

 任务信号量直接内嵌在UCOSIII中,使用也十分方便,今日学习使用一下:

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

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

目录

任务内嵌信号量:

实验目标解释:

目前各个文件任务:

#include "main.h"

#include "ComTask.h"

 #include "MessageTask.h"

 #include "CalculateTask.h"

测试效果截图: 

 测试工程下载:


 

任务内嵌信号量:

 

 

  • 请求次数的确定:任务内嵌信号量的请求次数并不是直接通过某个设置来确定的,而是通过信号量的发送和接收操作来管理的。每当一个任务发送信号量时,接收任务的信号量值就会增加,从而允许接收任务进行相应次数的请求。
  • 示例:假设任务A向任务B发送了3次信号量,那么任务B就可以请求3次任务内嵌信号量。每次请求成功后,任务B的信号量值就会减1,直到信号量值为0时,任务B再次请求信号量将会挂起等待。

 

实验目标解释:

ComTask 先将CalculateTask删除,随后每隔10秒发送一次系统内建信号量(循环发送五次信号量),

MessageTask等待请求得到系统内建信号量在运行,请求到了就打印自己运行次数

目前各个文件任务:

 

#include "main.h"

创建开始任务初始化每个基本任务,虽然有信号量与互斥信号量创建,但本文实际用不到!

#include "main.h"

void start_task(void *p_arg);//开始任务函数


int main(void)
{
	OS_ERR err;
	CPU_SR_ALLOC();
  Init_ALL();
	OSInit(&err);		//初始化UCOSIII
	
	OS_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);  //开启UCOSIII

	while(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 > 0u
   OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();	
#endif

#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(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();	//进入临界区
	//创建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  )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);
				 
	//创建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 "ComTask.h"

#include "ComTask.h"


/*
	ComTask 
	删除CalculateTask 
	延时10s
	向 MessageTask 发布 系统内建信号量 //循环发送五次信号量
	ComTask 计数打印自己运行次数
*/	

void comTask(void * p_arg)
{
	OS_ERR err;
	int i=0,OSTime_tickRate,j;
	
	//char ComTask_str[]="ComTask_write";
	
	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 提示
	
	while (DEF_TRUE)
	{
		OSTimeDlyHMSM(0,0,10,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时10s
		i++;
		//循环发送五次信号量
		for(j=0;j<5;j++)
		{
			OSTaskSemPost(&MessageTaskTaskTCB,OS_OPT_POST_NONE,&err);
		}
		UsartPrintf(USART1, "ComTask Post SEM to MessageTask\r\n");	 //ComTask 向 MessageTask 发布了 系统内建信号量
		
		UsartPrintf(USART1, "ComTask Print %d\r\n",i);	//打印 ComTask 运行次数
	}
}

 

 #include "MessageTask.h"

 

#include "MessageTask.h"

/*
	MessageTask
	等待-请求系统内建信号量
	有信号量允许次数就
	打印自己运行次数
		延时500ms	
*/
void MessageTask (void * p_arg)
{
	OS_ERR err;
	int i=0;
	
	//char MessageTask_str[]="MessageTask_write";
	
	p_arg = p_arg;
	while (DEF_TRUE)
	{
		i++;	
		OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err); //请求任务内建信号量
		UsartPrintf(USART1, "Signal Count remining %d times\r\n",MessageTaskTaskTCB.SemCtr);	//打印信号量剩余次数			
		UsartPrintf(USART1, "MessageTask Print %d \r\n",i);	                                  //打印自己运行次数
		OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err);                                //延时500ms			
	}
	
}

 

 #include "CalculateTask.h"

 在本文一开始就被ComTask 删除了,不做解释

 

测试效果截图: 

 解释都在截图里了:

如果没有任务内建信号量次数限制的话

以 MessageTask 的0.5 秒的速率,在ComTask俩次间隔不会只运行 5次

 

 测试工程下载:

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

 https://download.csdn.net/download/qq_64257614/90149144?spm=1001.2014.3001.5503