十七: 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) /**/
/***************************************************************/
static void TIM_CallBack1(void);
static void TIM_CallBack2(void);


#include "FreeRTOSConfig.h"
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"

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

/* LED任务句柄 */	
static TaskHandle_t LED1_Task_Handle= NULL;	
//static TaskHandle_t UART_Task_Handle= NULL;	
static TaskHandle_t KEY_Task_Handle = NULL;	
//static xTaskHandle  pv_handle = NULL;
#define TASK_STACK_SIZE 32

#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)
#define BIT_ALL (BIT_0 | BIT_1)
static EventGroupHandle_t xCreatedEventGroup = NULL;


/* 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任务主体
  * @ 参数    :   
  * @ 返回值  : 无
    ********************************************************************/

static void vLED1_Task (void *pvParameters)
{
	bool LedState = false;
	
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 500;
	
	/* 获取当前的系统时间 */
	xLastWakeTime = xTaskGetTickCount();
	
	while (1) {
		
		LedState = (bool) !LedState;
		Board_LED_Set(0, LedState);

//		vTaskDelay(500);
		/* vTaskDelayUntil 是绝对延迟, vTaskDelay 是相对延迟。 */
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
		
	}
}


static void vKEY_task(void* pvParameters)
{
	bool KeyState = false;
//	EventBits_t uxBits;
	
	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:
				{
					KeyState=!KeyState;
					if(KeyState)
					{
						printf("KEY1挂起任务LED\r\n");
						vTaskSuspend(LED1_Task_Handle);
					}
					else
					{
					
						printf("KEY1恢复任务LED\r\n");
						vTaskResume(LED1_Task_Handle);
					}
				}break;
				case 2:
				{
					/* 打印系统时钟节拍数 */
					printf("当前的系统时钟节拍数 = %d\r\n", xTaskGetTickCount());
					
					/* K2键按下,直接发送事件标志给任务vTaskMsgPro,设置bit0 */
					
					printf("K2键按下,启动单次定时器中断,100ms后在定时器中断给任务vTaskMsgPro发送事件标志\r\n");
					bsp_HardTimer(2,(void *)TIM_CallBack1);


					
				}break;
				case 3:
				{
					/* K3键按下,直接发送事件标志给任务vTaskMsgPro,设置bit1 */
					
					printf("K3键按下,启动单次定时器中断,1s后在定时器中断给任务vTaskMsgPro发送事件标志\r\n");
					bsp_HardTimer(3,(void *)TIM_CallBack2);


					
				}break;
				default:break;
			}
			key2=0;
		}


			
	}
}


/*
*********************************************************************************************************
*	函 数 名: vTaskMsgPro
*	功能说明: 消息处理,使用函数xEventGroupWaitBits接收任务vTaskTaskUserIF发送的事件标志
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*   优 先 级: 3  
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
	bool LedState = false;
	EventBits_t uxBits;
	const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; /* 最大延迟100ms */
	
    while(1)
    {
    	/* 等K2按键按下设置bit0和K3按键按下设置bit1 */
    	uxBits = xEventGroupWaitBits(xCreatedEventGroup, /* 事件标志组句柄 */
    						         BIT_ALL,            /* 指定的标志位,等待bit0和bit1被设置 */
    						         pdTRUE,             /* 为 pdTRUE,指定的标志位全部被置 1才返回。pdFALSE,指定的任何标志位被置1都返回。*/
    						         pdTRUE,             /* 设置为pdTRUE表示等待bit1和bit0都被设置,pdFALSE表示只有一个置位*/
    						         xTicksToWait); 	 /* 等待延迟时间 ,标志位没有置位时超过这个时间将返回。如果设置为 portMAX_DELAY,表示永久等待。*/
    	
    	if((uxBits & BIT_ALL) == BIT_ALL)
    	{
    		/* 接收到bit1和bit0都被设置的消息 */
    		printf("uxBits =%d\n",uxBits);
    		printf("接收到bit0和bit1都被设置的消息\r\n");
    		
    		LedState = !LedState;
    		Board_LED_Set(2, LedState);


		}
		else
		{
			/* 超时,另外注意仅接收到一个按键按下的消息时,变量uxBits的相应bit也是被设置的 */
			//即超过xTicksToWait所设定的时间时返回。
			
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: AppObjCreate
*	功能说明: 创建任务通信机制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void AppObjCreate (void)
{
	/* 创建事件标志组 */
	xCreatedEventGroup = xEventGroupCreate();
	
	if(xCreatedEventGroup == NULL)
	{
	    /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
		printf("创建任务时间标志失败\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");

 	}



}

/*
*********************************************************************************************************
*	函 数 名: TIM_CallBack1和TIM_CallBack2
*	功能说明: 定时器中断的回调函数,此函数被bsp_HardTimer所调用。		  			  
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void TIM_CallBack1(void)
{
	BaseType_t xResult;
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;//高优先级任务是否被唤醒的状态保存
	
	/* 向任务vTaskMsgPro发送事件标志 (需要在宏中开启)*/
	xResult = xEventGroupSetBitsFromISR(xCreatedEventGroup, /* 事件标志组句柄 */
									    BIT_0 ,             /* 设置bit0 */
									    &xHigherPriorityTaskWoken );
	
	/* 消息被成功发出 */
	if( xResult != pdFAIL )
	{
		printf("BIT0消息已发出\n");
		/* 如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	}
	Board_LED_Toggle(5);


	
}

 void TIM_CallBack2(void)
{
	BaseType_t xResult;
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	
	/* 向任务vTaskMsgPro发送事件标志 */
	xResult = xEventGroupSetBitsFromISR(xCreatedEventGroup, /* 事件标志组句柄 */
									    BIT_1,              /* 设置bit1 */
									    &xHigherPriorityTaskWoken );//高优先级任务是否被唤醒的状态保存
	
	/* 消息被成功发出 */
	if( xResult != pdFAIL )
	{
		printf("BIT1消息已发出\n");
		/* 如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	}
	Board_LED_Toggle(6);//亮灭1s

}

任务标志事件

  1. 按键任务里
    按键任务里置位标志
    按下按键2,函数指针赋值为回调函数1。
    按下按键3,函数指针赋值为调用回调函数2。
  2. 定时器里
    回调函数1,100ms后定时器ch2中断给任务vTaskMsgPro发送事件bit0标志。
    回调函数2,1s后定时器ch3中断给任务vTaskMsgPro发送事件bit1标志。
  3. 消息任务里
    两个标志同时置位后,翻转LED2。
  4. 实验现象
    按下按键2,LED5状态翻转。按下按键3,LED3状态翻转。
  5. 函数:
	xEventGroupCreate();
	xEventGroupSetBits();
	xEventGroupWaitBits();
	xEventGroupSetBitsFromISR();

​ 函数 xEventGroupSetBitsFromISR 是用于中断服务程序中调用的,任务代码中使用的是 xEventGroupSetBits。
​ 使用前一定要保证事件标志已经通过函数 xEventGroupCreate 创建了。
同时要在 FreeRTOSConfig.h 文件中使能如下三个宏定义:

   #define INCLUDE_xEventGroupSetBitFromISR 1
   #define configUSE_TIMERS 1
   #define INCLUDE_xTimerPendFunctionCall 1
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐