📄 消息队列.c
字号:
/**********************************************************************************************************
*
* 电子科技大学嵌入式软件工程中心 版权所有
*
* Copyright (C) 2007 UESTC ESEC
*
**********************************************************************************************************/
/**********************************************************************************************************
* 目的:
* 这个程序演示基本的消息队列。程序启动设计了6个普通应用任务以及一个控制任务TAC,等待消息的任务总是按照优先级的高低来决定获得
* 消息的顺序,实现消息队列的使用。
**********************************************************************************************************/
#include "../ucos/includes.h"
#include "../bsp/Uart.h"
extern T_UART_PORT uartPort0;
extern void ucBsp_Init(void);
extern void Timer_Start(void);
extern void CPSR_Init(void);
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
#define TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */
#define N_TASKS 3 /* Number of tasks which wait for queue1 */
/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/
OS_STK TaskStk1[N_TASKS][TASK_STK_SIZE]; /* Tasks stacks */
OS_STK TaskStk2[N_TASKS][TASK_STK_SIZE];
OS_STK TaskStartStk[TASK_STK_SIZE]; /* Startup task stack */
OS_STK TaskConStk[TASK_STK_SIZE];
//OS_STK TaskQueryStk[TASK_STK_SIZE];
INT8U TaskData1[N_TASKS]; /* Parameters to pass to each task */
INT8U TaskData2[N_TASKS];
OS_EVENT *q1; /* 2 queue */
OS_EVENT *q2;
void *Msg1[6]; /* 2 arry for msg */
void *Msg2[6];
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void Taskq1(void *pdata); /* Function prototypes of taskq1s */
void Taskq2(void *pdata); /* Function prototypes of taskq2s */
void TaskStart(void *pdata); /* Function prototypes of Startup task */
void TaskCon(void *pdata); /* Function prototypes of Control task */
void TaskQuery();
static void TaskStartCreateTasks(void);
void TaskQuery(void);
/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
int main (void)
{
//板级初始化
ucBsp_Init();
//open the interrupt bit 'I'
CPSR_Init();
//Initialize uC/OS-II
OSInit();
Uart_PutString(uartPort0,"\t本程序演示uC/OS-II消息队列管理的基本思想和策略: ");
Uart_PutLine(uartPort0,"程序启动设计了6个普通应用任\n\r务以及一个控制任务TAC,等待消息的任务总是按照优先级的高低来决定获得消息的顺序,实现消息\n\r队列的使用");
Uart_PutString(uartPort0,"请按任意键继续......");
Uart_GetChar(uartPort0);
Uart_PutLine(uartPort0,"");
//建立消息队列
q1 = OSQCreate(&Msg1[0],6);
q2 = OSQCreate(&Msg2[0],6);
OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
//Start multitasking
OSStart();
return 1;
}
/*
*********************************************************************************************************
* STARTUP TASK
*********************************************************************************************************
*/
void TaskStart (void *pdata)
{
pdata = pdata;
Timer_Start();
TaskStartCreateTasks();
OSTaskSuspend(OS_PRIO_SELF);
}
/*
***************************************************************************************************************
* CREATE TASKS
***************************************************************************************************************
*/
void TaskStartCreateTasks (void)
{
INT8U i;
//Create N_TASKS+N_TASKS identical tasks
for (i = 0; i <N_TASKS; i++)
{
TaskData1[i] = i;
OSTaskCreate(Taskq1, (void *)&TaskData1[i], &TaskStk1[i][TASK_STK_SIZE - 1], i+1);
}
for (i = 0; i <N_TASKS; i++)
{
TaskData2[i] = i;
OSTaskCreate(Taskq2, (void *)&TaskData2[i], &TaskStk2[i][TASK_STK_SIZE - 1], i+4);
}
//Create control tasks
OSTaskCreate(TaskCon, (void *)0, &TaskConStk[TASK_STK_SIZE - 1],i+4);
}
/*
*********************************************************************************************************
* TASKq1
*********************************************************************************************************
*/
void Taskq1 (void *pdata)
{
INT8U err;
INT8U id;
void *mg;
id=*(int *)pdata;
for (;;)
{
//等待消息队列中的消息
//OSQPend()函数用于任务等待消息。
//消息通过中断或另外的任务发送给需要的任务。
//消息是一个以指针定义的变量,在不同的程序中消息的使用也可能不同。
//如果调用OSQPend()函数时队列中已经存在需要的消息,那么该消息被返回给OSQPend()函数的调用者,队列中清除该消息。
//如果调用OSQPend()函数时队列中没有需要的消息,OSQPend()函数挂起当前任务直到得到需要的消息或超出定义的超时时间。
//如果同时有多个任务等待同一个消息,μC/OS-Ⅱ默认最高优先级的任务取得消息并且任务恢复执行。
// 一个由OSTaskSuspend()函数挂起的任务也可以接受消息,但这个任务将一直保持挂起状态直到通过调用OSTaskResume()函数恢复任务的运行。
mg=OSQPend(q1,0,&err);
Uart_PutLine(uartPort0,"Task__%d got a Message:\t %s",id,(char *)mg);
//Wait 2 second
//按照时、分、秒、毫秒进行延时的函数
OSTimeDlyHMSM(0, 0, 2, 0);
}
}
/*
*********************************************************************************************************
* TASKq2
*********************************************************************************************************
*/
void Taskq2 (void *pdata)
{
INT8U err;
INT8U id;
void *mg;
id=*(int *)pdata;
for (;;)
{
OSTimeDlyHMSM(0, 0, 2, 0);
mg=OSQPend(q2,0,&err);
switch(err)
{
case OS_NO_ERR:
Uart_PutLine(uartPort0,"\tTask__%d got:\t%s.", id+3, (char *)mg);
OSTimeDlyHMSM(0, 0, 0, 200*(4-id));
break;
default :
Uart_PutLine(uartPort0, "Queue__2 is EMPTY!,Task__%d cannot get message!",id+3);
OSTimeDlyHMSM(0, 0, 0, 200*(4-id));
break;
}
}
}
/*
*********************************************************************************************************
* TASKcon
*********************************************************************************************************
*/
void TaskCon (void *pdata)
{
INT8U i,j;
INT8U err;
INT8U note=1; /* for flush the queue */
//queue1's message
static char *s[]={
"message___0",
"message___1",
"message___2",
"message___3",
"message___4",
"message___5"
};
//queue2's message
static char *t[]={
"message___A",
"message___B",
"message___C",
"message___D",
"message___E",
"message___F"
};
pdata=pdata;
for (;;)
{
Uart_PutLine(uartPort0,"");
Uart_PutLine(uartPort0,"-------------Add message to queue1-------------");
Uart_PutLine(uartPort0,"");
for( i = 0 ; i < 6 ; i++ )
{
//向消息队列发送一则消息,插在前面(LIFO)
err = OSQPostFront(q1,(void*)s[i]);
switch(err)
{
case OS_NO_ERR:
Uart_PutLine(uartPort0,"\tQueue1___%d add:\t%s",i,s[i]);
OSTimeDlyHMSM(0, 0, 0, 150);
break;
case OS_Q_FULL:
Uart_PutLine(uartPort0,"Queue1 is full, cannot added!");
OSTimeDlyHMSM(0, 0, 0, 150);
break;
default :break;
}
}
Uart_PutLine(uartPort0,"");
Uart_PutLine(uartPort0,"-------------Add message to queue2-------------");
Uart_PutLine(uartPort0,"");
for( j = 0 ; j < 6 ; j++ )
{
//OSQPost()函数通过消息队列向任务发送消息。
//消息是一个指针长度的变量,在不同的程序中消息的使用也可能不同。
//如果队列中已经存满消息,返回错误码。
//OSQPost()函数立即返回调用者,消息也没有能够发到队列。
//如果有任何任务在等待队列中的消息,最高优先级的任务将得到这个消息。
//如果等待消息的任务优先级比发送消息的任务优先级高,那么高优先级的任务将得到消息而恢复执行,也就是说,发生了一次任务切换。
//消息队列是先入先出(FIFO)机制的,先进入队列的消息先被传递给任务。
err = OSQPost(q2,(void*)t[j]);
switch(err)
{
case OS_NO_ERR:
//消息已经放入消息队列
Uart_PutLine(uartPort0,"\tQueue2__%d add:\t%s",j,t[j]);
OSTimeDlyHMSM(0, 0, 0, 150);
break;
case OS_Q_FULL:
//消息队列已满
Uart_PutLine(uartPort0,"Queue2 FULL!cannot add.");
OSTimeDlyHMSM(0, 0, 0, 150);
break;
default :
break;
}
}
if(note==1)
{
//OSQFlush()函数清空消息队列并且忽略发送往队列的所有消息。
//不管队列中是否有消息,这个函数的执行时间都是相同的。
OSQFlush(q1);
Uart_PutLine(uartPort0,"\n\r--------------Queue1 Cleared Up--------------\n\r");
note=0;
}
else
{
OSQFlush(q2);
Uart_PutLine(uartPort0,"\n\r--------------Queue2 Cleared Up--------------\n\r");
note=1;
}
TaskQuery();
}
}
void TaskQuery()
{
INT8U err;
OS_Q_DATA data;
//取得消息队列本身的消息
//OSQQuery()函数用来取得消息队列的信息。
//用户程序必须建立一个OS_Q_DATA的数据结构,该结构用来保存从消息队列的事件控制块得到的数据。
//通过调用OSQQuery()函数可以知道任务是否在等待消息、有多少个任务在等待消息、队列中有多少消息以及消息队列可以容纳的消息数。
//OSQQuery()函数还可以得到即将被传递给任务的消息的信息。
err=OSQQuery(q1,&data);
if(err==OS_NO_ERR)
{
Uart_PutLine(uartPort0,"\n\r------------Queue1's Information------------");
Uart_PutLine(uartPort0,"\tNextMsg:\t%s\n\r",(char *)data.OSMsg);
Uart_PutLine(uartPort0,"\tNumMsg:\t%d",data.OSNMsgs);
Uart_PutLine(uartPort0,"\tQSize:\t%d",data.OSQSize);
Uart_PutLine(uartPort0,"----------------------------------------------");
}
OSTimeDlyHMSM(0, 0, 3, 500);
err=OSQQuery(q2,&data);
if(err==OS_NO_ERR)
{
Uart_PutLine(uartPort0,"\n\r------------Queue2's Information------------");
Uart_PutLine(uartPort0,"\tNextMsg:\t%s\n\r",(char *)data.OSMsg);
Uart_PutLine(uartPort0,"\tNumMsg:\t%d",data.OSNMsgs);
Uart_PutLine(uartPort0,"\tQSize:\t%d",data.OSQSize);
Uart_PutLine(uartPort0,"----------------------------------------------");
}
OSTimeDlyHMSM(0, 0, 3, 500);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -