UCOSIII消息队列

一、相关理论
1、消息是指向数据的指针,可以是任务块或者是函数。
2、任务的传递是指针传递,不是值的传递,(数据的本身不产生拷贝)。
3、UCOSIII对消息的读取可以说(FIFO)先进先出,也可以先进后出(LIFO)。
二、相关API函数
1、定义消息队列

#define KEY_Q_NUM   1 		//消息队列长度
OS_Q KEY_Msg;				//定义一个消息队列

2、OSQCreate() 创建消息队列

OSQCreate	(	(OS_Q*)			&KEY_Msg,
             (CPU_CHAR*)		"KEY_Msg",
             (OS_MSG_QTY)   KEY_Q_NUM,
             (OS_ERR*)      &err);

void OSQCreate (	OS_Q *p_q,				//指向消息队列
		CPU_CHAR *p_name,		//消息队列名字
		OS_MSG_QTY max_qty,	//消息队列长度
		OS_ERR *p_err)

3、OSQPend() 等待消息队列

num=OSQPend(  &KEY_Msg, 0 , OS_OPT_PEND_BLOCKING, &size, 0, &err);

void *OSQPend (	OS_Q *p_q,					//指向消息队列
		OS_TICK timeout,			//等待超时时间
		OS_OPT opt,				//是否使用阻塞
		OS_MSG_SIZE *p_msg_size,	//接收消息长度
		CPU_TS *p_ts,				//时间戳
		OS_ERR *p_err)

4、OSQPost() 向消息队列发送消息

OSQPost ( &KEY_Msg, &task1_num, 10, OS_OPT_POST_FIFO, &err);

void OSQPost (		OS_Q *p_q,		//指向消息对列
		void *p_void,	//向消息对列发送的消息
		OS_MSG_SIZE msg_size,	//发送消息的长度
		OS_OPT opt,	//选择消息发送的选项
		OS_ERR *p_err)
OS_OPT opt  OS_OPT_POST_ALL 将消息发送给所有等待该消息队列的任务,
需要和OS_OPT_POST_FIFO 或者OS_OPT_POST_LIFO 配合使用。
OS_OPT_POST_FIFO 待发送消息保存在消息队列的末尾
OS_OPT_POST_LIFO 待发送的消息保存在消息队列的开头
OS_OPT_POST_NO_SCHED 禁止在本函数内执行任务调度。
我们可以使用上面四种基本类型来组合出其他几种类型,如下:
OS_OPT_POST_FIFO + OS_OPT_POST_ALL
OS_OPT_POST_LIFO + OS_OPT_POST_ALL
OS_OPT_POST_FIFO + OS_OPT_POST_NO_SCHED
OS_OPT_POST_LIFO + OS_OPT_POST_NO_SCHED

三、实验设计
设计一个程序,4个任务,两个消息队列,一个定时器。任务1用于按键检测,并将按键次数通过 KEY_Msg 消息队列发送给任务2,任务二等待一直等待消息队列,等待到消息对列后把按键次数打印到串口。定时器1的回调函数把自身运行次数通过 DATA_Msg 消息队列发送给任务3,任务3把接收到的数据通过串口打印出来。
四、程序源码

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "bsp_key.h"  
#include "usart.h"
#include "includes.h"

//任务优先级
#define START_TASK_PRIO		3
//任务堆栈大小	
#define START_STK_SIZE 		512
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈	
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);

//任务优先级
#define TASK1_TASK_PRIO		4
//任务堆栈大小	
#define TASK1_STK_SIZE 		128
//任务控制块
OS_TCB Task1TaskTCB;
//任务堆栈	
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
//任务函数
void task1_task(void *p_arg);

//任务优先级
#define TASK2_TASK_PRIO		5
//任务堆栈大小	
#define TASK2_STK_SIZE 		128
//任务控制块
OS_TCB Task2TaskTCB;
//任务堆栈	
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
//任务函数
void task2_task(void *p_arg);

//任务优先级
#define TASK3_TASK_PRIO		6
//任务堆栈大小	
#define TASK3_STK_SIZE 		128
//任务控制块
OS_TCB Task3TaskTCB;
//任务堆栈	
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];
//任务函数
void task3_task(void *p_arg);


//OS_SEM	MY_SEM;		//定义一个信号量,用于访问共享资源
#define KEY_Q_NUM   1 	//消息队列长度
#define DATA_Q_NUM  4  
OS_Q KEY_Msg;						//定义一个消息队列
OS_Q DATA_Msg;

OS_TMR tmr1;
u8 task1_num=0;
u8 Tmr_num=0;

void tmr1_callback(void);

int main(void)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	
	delay_init ();
	NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);  //设置中断优先级
	uart_init (115200);				//初始化串口
	printf("串口初始化完成\r\n");
	LED_Init();
	Key_GPIO_Config();
	
	OSInit(&err);
	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);
	
}

//开始任务函数
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_CRITICAL_ENTER();	//进入临界区
	OSQCreate	( (OS_Q*)			&KEY_Msg,
                 (CPU_CHAR*)		"KEY_Msg",
                 (OS_MSG_QTY)   KEY_Q_NUM,
                 (OS_ERR*)      &err);
								 
	OSQCreate	( (OS_Q*)			&DATA_Msg,
                 (CPU_CHAR*)		"DATA_Msg",
                 (OS_MSG_QTY)   DATA_Q_NUM,
                 (OS_ERR*)      &err);
	
	OSTmrCreate (	(OS_TMR*)			&tmr1,
                   (CPU_CHAR*)			"tmr1",
                   (OS_TICK )        0,				//初始化延时20*10=200ms
                   (OS_TICK)         200,				// 100*10=1000ms
                   (OS_OPT)          OS_OPT_TMR_PERIODIC,
                   (OS_TMR_CALLBACK_PTR)  tmr1_callback,
                   (void*)						0,
                   (OS_ERR*)					&err);
	
									 
	OSTaskCreate(	(OS_TCB*)			&Task1TaskTCB,			//任务控制块
                    (CPU_CHAR*)		"task1_task ",			//任务名称
                    (OS_TASK_PTR)   task1_task,				//任务函数
                    (void*)          0,									//参数
                    (OS_PRIO)       TASK1_TASK_PRIO,		//任务优先级
                    (CPU_STK*)      &TASK1_TASK_STK[0],
                    (CPU_STK_SIZE)  TASK1_STK_SIZE/10,
                    (CPU_STK_SIZE)  TASK1_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);
										
	OSTaskCreate(	 (OS_TCB*)			&Task2TaskTCB,			//任务控制块
                    (CPU_CHAR*)		"task2_task ",			//任务名称
                    (OS_TASK_PTR)   task2_task,		//任务函数
                    (void*)          0,									//参数
                    (OS_PRIO)       TASK2_TASK_PRIO,		//任务优先级
                    (CPU_STK*)      &TASK2_TASK_STK[0],
                    (CPU_STK_SIZE)  TASK2_STK_SIZE/10,
                    (CPU_STK_SIZE)  TASK2_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);
									
	OSTaskCreate(	 (OS_TCB*)			&Task3TaskTCB,			//任务控制块
                    (CPU_CHAR*)		"task3_task ",			//任务名称
                    (OS_TASK_PTR)   task3_task,		//任务函数
                    (void*)          0,									//参数
                    (OS_PRIO)       TASK3_TASK_PRIO,		//任务优先级
                    (CPU_STK*)      &TASK3_TASK_STK[0],
                    (CPU_STK_SIZE)  TASK3_STK_SIZE/10,
                    (CPU_STK_SIZE)  TASK3_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);
										
	OS_CRITICAL_EXIT();	//退出临界区
	OSTaskDel ((OS_TCB*)&StartTaskTCB,&err);			//删除任务自身
}

void task1_task(void *p_arg)
{

	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	

	while(1)
	{
		if(PAin(0)==1)
		{
			task1_num++;
			OSQPost ( &KEY_Msg, &task1_num, 10, OS_OPT_POST_FIFO, &err);
			while(PAin(0)==1);
		}
			OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时500MS
	}

}

void task2_task(void *p_arg)
{
	u8 *num;
	OS_ERR err;
	CPU_SR_ALLOC();
	OS_MSG_SIZE size;
	p_arg = p_arg;
	
	while(1)
	{
		num=OSQPend(  &KEY_Msg, 0 , OS_OPT_PEND_BLOCKING, &size, 0, &err);
		printf("按键次数 %d\r\n",*num);
		LED1=~LED1;
		OSTimeDlyHMSM(0,0,3,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
	}
}

void task3_task(void *p_arg)
{
	u8 *num2;
	OS_ERR err;
	CPU_SR_ALLOC();
	OS_MSG_SIZE size;
	p_arg = p_arg;
	OSTmrStart (&tmr1, &err);
	
	while(1)
	{
		num2=OSQPend(  &DATA_Msg, 0 , OS_OPT_PEND_BLOCKING, &size, 0, &err);	
		printf("定时器运行次数 %d\r\n",*num2);
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
	}
}


void tmr1_callback(void)
{
	OS_ERR err;
	
	Tmr_num++;
	OSQPost ( &DATA_Msg, &Tmr_num, 10, OS_OPT_POST_FIFO, &err);
}

你可能感兴趣的:(stm32,UCOSIII)