⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 消息队列.c

📁 这个程序演示基本的消息队列。程序启动设计了6个普通应用任务以及一个控制任务TAC,等待消息的任务总是按照优先级的高低来决定获得消息的顺序,实现消息队列的使用。
💻 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 + -