18 freertos消息队列-任务通信

本文档展示了如何使用FreeRTOS消息队列在任务间进行通信。通过创建两个任务,一个负责按键处理,另一个负责LED控制,按键任务根据按键输入向消息队列发送数据,LED任务从消息队列接收数据并更新LED状态。此外,还有一个任务用于处理消息队列中的数据。实验中,按键2触发向队列1发送整数,按键3触发向队列2发送结构体数据,实现了任务间的实时通信和状态交互。
摘要由CSDN通过智能技术生成

十八:18 freertos消息队列-任务通信

试验源码:

#include <stdio.h>
#include "board.h"
#include "led.h"
#include "key.h"
#include "uart.h"
//#include "tim_mrt.h"


/*** System oscillator rate and clock rate on the CLKIN pin  ****/
/**/const uint32_t OscRateIn = MAIN_OSC_XTAL_FREQ_HZ;		 /**/
/**/const uint32_t ExtRateIn = EXT_CLOCK_IN_FREQ_HZ;		 /**/
 //系统复位
#define	System_restart	(LPC_SWM->PINENABLE0 = 0xffffffffUL) /**/
/***************************************************************/



#include "FreeRTOSConfig.h"
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"//事件头文件
#include "queue.h"//队列头文件


/**************************** 任务句柄 ********************************/
/* 
 * 任务句柄是一个指针,用于指向一个任务。
 */

/* LED任务句柄 */	
static TaskHandle_t LED1_Task_Handle= NULL;	
static xTaskHandle KEY_Task_Handle = NULL;	

#define TASK_STACK_SIZE 32


static QueueHandle_t xQueue1 = NULL;
static QueueHandle_t xQueue2 = NULL;
typedef struct Msg
{
	uint8_t  ucMessageID;
	uint16_t usData[2];
	uint32_t ulData[2];
}MSG_T;

MSG_T   g_tMsg; /* 定义一个结构体用于消息队列 */



/* Sets up system hardware 
**********************************************************************
  * @ 函数名  : BSP_Init
  * @ 功能说明: 板级外设初始化,所有板子上的初始化均可放在这个函数里面
  * @ 参数    :   
  * @ 返回值  : 无
*********************************************************************/
static void prvSetupHardware(void)
{

	SystemCoreClockUpdate();

	DEBUGINIT();
	led_Init() ;	
	Key_INIT();
//	MRT_Init();

	Board_UARTPutSTR("build date: " __DATE__ " build time: " __TIME__ "\n");

}


/**********************************************************************
  * @ 函数名  : vLED_Task0
  * @ 功能说明: LED_Task任务主体,接收任务 vKEY_task 发送的消息队列数据(xQueue2)
  * @ 参数    :   
  * @ 返回值  : 无
  ********************************************************************/

static void vLED1_Task (void *pvParameters)
{
	

	MSG_T *ptMsg;
	BaseType_t xResult;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200); /* 设置最大等待时间为200ms */
	
	while (1) {
		
//		vTaskDelay(10);
		xResult = xQueueReceive(xQueue2,                   /* 消息队列句柄 */
		                        (void *)&ptMsg,  		   /* 这里获取的是结构体的地址 */
		                        (TickType_t)xMaxBlockTime);/* 设置阻塞时间 */
		vTaskDelay(100);						
		if(xResult == pdPASS)
		{
			/* 成功接收,并通过串口将数据打印出来 */
			printf("接收到消息队列数据 ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
			printf("接收到消息队列数据 ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
			printf("接收到消息队列数据 ptMsg->usData[0] = %d\r\n", ptMsg->usData[0]);
			
			Board_LED_Toggle(0);
		
		}
		else
		{
			/* 超时 */
			Board_LED_Toggle(2);
			Board_LED_Toggle(3);
		}
		
	}
}

/*
*********************************************************************************************************
*	函 数 名: vKEY_task
*	功能说明: 按键任务
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
*********************************************************************************************************
*/
static void vKEY_task(void* pvParameters)
{

	MSG_T   *ptMsg;
	uint8_t ucCount = 0;
	uint8_t pcWriteBuffer[200];
	
	/* 初始化结构体指针 */
	ptMsg = &g_tMsg;
	
	/* 初始化数组 */
	ptMsg->ucMessageID = 0;
	ptMsg->ulData[0] = 0;
	ptMsg->usData[0] = 0;
	
	u8 key2=0;
	while(1)
	{
		u8 key=0;
		if(Scan_Key())
			vTaskDelay(20);
		else continue;
		if(!Scan_Key())continue;
		else
		{
			key=Scan_Key();
			key2=key;
		}
		
		while(Scan_Key()){};//等按键抬起

		if(key2)
		{

			switch(key2)
			{
				case 1:
				{
					printf("=================================================\r\n");
					printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
					vTaskList((char *)&pcWriteBuffer);
					printf("%s\r\n", pcWriteBuffer);
				 
				}break;
				case 2:
				{
					 /* K2键按下,向xQueue1发送数据 */
					ucCount++;
				
					/* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
					if( xQueueSend(xQueue1,
								   (void *) &ucCount,
								   (TickType_t)10) != pdPASS )
					{
						/* 发送失败,即使等待了10个时钟节拍 */
						printf("K2键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
					}
					else
					{
						/* 发送成功 */
						printf("K2键按下,向xQueue1发送数据成功\r\n");						
					}
					
				}break;
				case 3:
				{
					 /* K3键按下,向xQueue2发送数据 */
					ptMsg->ucMessageID++;
					ptMsg->ulData[0]++;;
					ptMsg->usData[0]++;
					/* 使用消息队列实现指针变量的传递 */
					if(xQueueSend(xQueue2,                  /* 消息队列句柄 */
								 (void *) &ptMsg,           /* 发送结构体指针变量ptMsg的地址 */
								 (TickType_t)10) != pdPASS )
					{
						/* 发送失败,即使等待了10个时钟节拍 */
						printf("K3键按下,向 xQueue2 发送数据失败,即使等待了10个时钟节拍\r\n");
					}
					else
					{
						/* 发送成功 */
						printf("K3键按下,向 xQueue2 发送数据成功 \r\n");						
					}
 					
				}break;
				default:break;
			}
			key2=0;
		}
		

			
	}
}


/*
*********************************************************************************************************
*	函 数 名: vTaskMsgPro
*	功能说明: 使用函数 xQueueReceive 接收任务 vKEY_task 发送的消息队列数据(xQueue1)
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 3  
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
	BaseType_t xResult;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms */
	uint8_t ucQueueMsgValue;
	
	
    while(1)
    {
		/* 获取K2按键按下的消息队列 */
		xResult = xQueueReceive(xQueue1,                   /* 消息队列句柄 */
		                        (void *)&ucQueueMsgValue,  /* 存储接收到的数据到变量ucQueueMsgValue中 */
		                        (TickType_t)xMaxBlockTime);/* 设置阻塞时间 */
								
		if(xResult == pdPASS)
		{
			/* 成功接收,并通过串口将数据打印出来 */
			printf("接收到消息队列数据ucQueueMsgValue = %d\r\n", ucQueueMsgValue);
			Board_LED_Toggle(1);
		}
		else
		{
			/* 超时 */
			
			Board_LED_Toggle(4);
		}
		
    }
}

/*
*********************************************************************************************************
*	函 数 名: AppObjCreate
*	功能说明: 创建任务通信机制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void AppObjCreate (void)
{
	/* 创建10个uint8_t型消息队列 */
	xQueue1 = xQueueCreate(10, sizeof(uint8_t));
    if( xQueue1 == 0 )
    {
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
    
		DEBUGSTR("队列1创建失败\n");
		
	}
	
	/* 创建10个存储指针变量的消息队列,由于CM3/CM4内核是32位机,一个指针变量占用4个字节 */
	xQueue2 = xQueueCreate(10, sizeof(struct Msg *));
    if( xQueue2 == 0 )
    {
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
		DEBUGSTR("队列2创建失败\n");
		
    }
}
/***********************************************************************
  * @ 函数名  : AppTaskCreate
  * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
  * @ 参数    : 无  
  * @ 返回值  : 无
  **********************************************************************/
static void AppTaskCreate()
{
	BaseType_t xReturn=pdPASS;/*定义任务返回值*/
	
	taskENTER_CRITICAL();//进入临界区,禁止中断打断

 
	xReturn=xTaskCreate(vLED1_Task, 
						"vLED1_Task",
						TASK_STACK_SIZE*2, 
						NULL, 
						(tskIDLE_PRIORITY + 1UL),
						(TaskHandle_t *) &LED1_Task_Handle);

	xReturn=xTaskCreate(vKEY_task, 
						"vKEY_Task",
						TASK_STACK_SIZE*4, 
						NULL, 
						(tskIDLE_PRIORITY + 1UL),
						(TaskHandle_t *) &KEY_Task_Handle);
	
	xReturn=xTaskCreate(vTaskMsgPro, 
						"vTaskMsgPro",
						TASK_STACK_SIZE*5, 
						NULL, 
						(tskIDLE_PRIORITY + 3UL),
						NULL);
				
	if(pdPASS==xReturn)
	{
		printf("创建LED_Task任务成功\r\n");
	}	

	
	
	
	
//	 vTaskDelete(LED1_Task_Handle);//删除AppTaskCreate任务
//	 vTaskDelete(UART_Task_Handle);//删除AppTaskCreate任务

	
	taskEXIT_CRITICAL(); //退出临界区
	

}

/**
 * @brief	main routine for blinky example
 * @return	Function should not exit.
 */
int main(void)
{
	
	prvSetupHardware();
	Board_UARTPutSTR("LPC824 FreeRTOS 任务管理\n\r");
	printf("Key按下挂起任务,Key按下恢复任务\r\n");

	AppTaskCreate();
	
	/* 创建任务通信机制 */
	AppObjCreate();
	
	vTaskStartScheduler();//任务调度

	
	
	/* Loop forever */
	while (1) {
			printf("FreeRTOS 运行失败\n\r");
 	}
	
	
}

任务标志事件

  1. 按键任务里
    按键任务里置位标志
    按下按键2,向队列1里发送消息,每按一次发送的数据加1。
    按下按键3,向消息队列2里发数据,每按一次发送三组数据。

  2. LED任务,接收消息队列2的数据。

  3. 消息任务里
    两个标志同时置位后,翻转LED2。

  4. 实验现象
    按下按键2,LED1状态翻转。按下按键3,LED1状态翻转。

  5. 函数:

    xQueueCreate();
    xQueueReceive();
    xQueueSend();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值