17 freertos消息队列-任务通信
·
十七: 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
}
任务标志事件
- 按键任务里
按键任务里置位标志
按下按键2,函数指针赋值为回调函数1。
按下按键3,函数指针赋值为调用回调函数2。- 定时器里
回调函数1,100ms后定时器ch2中断给任务vTaskMsgPro发送事件bit0标志。
回调函数2,1s后定时器ch3中断给任务vTaskMsgPro发送事件bit1标志。- 消息任务里
两个标志同时置位后,翻转LED2。- 实验现象
按下按键2,LED5状态翻转。按下按键3,LED3状态翻转。- 函数:
xEventGroupCreate(); xEventGroupSetBits(); xEventGroupWaitBits(); xEventGroupSetBitsFromISR(); 函数 xEventGroupSetBitsFromISR 是用于中断服务程序中调用的,任务代码中使用的是 xEventGroupSetBits。
使用前一定要保证事件标志已经通过函数 xEventGroupCreate 创建了。
同时要在 FreeRTOSConfig.h 文件中使能如下三个宏定义:#define INCLUDE_xEventGroupSetBitFromISR 1 #define configUSE_TIMERS 1 #define INCLUDE_xTimerPendFunctionCall 1
更多推荐
所有评论(0)