一、概念
(1)FreeRTOS从V8.2.0版本开始提供任务通知
 (2)每个任务都有一个32位的通知值
 (3)发送任务通知的几种情况
 3.1 发送通知给任务,如果有通知未读,不覆盖通知值
 3.2 发送通知给任务,直接覆盖通知值
 3.3 发送通知给任务,设置通知值的一个或多个位,可以当做事件组来使用
 3.4 发送通知给任务,递增通知值,可以当做计数信号量来使用
 (4)只能有一个任务接收通知消息
 (5)只有等待通知的任务可以被阻塞
 (6)无需创建,属于任务控制块中的变量,创建任务时即创建完成
 (7)中断/任务均能发送通知
 (8)只有任务可以等待通知,而不允许中断中等待通知
 (9)相较于传统方式性能快
 (10)使用时需要使能configUSE_TASK_NOTIFICATIONS宏定义
二、使用函数
(1)xTaskNotifyGive发送通知,没有通知值(信号量类型)
 (2)xTaskNotify发送通知,带通知值
 (3)xTaskNotifyAndQuery发送通知,带通知值,并返回原通知值
 (4)ulTaskNotifyTake等待通知(信号量类型)
 (5)xTaskNotifyWait等待通知
 (6)vTaskNotifyGiveFromISR中断版本的xTaskNotifyGive
 (7)xTaskNotifyAndQueryFromISR中断版本的xTaskNotifyAndQuery
 (8)xTaskNotifyFromISR中断版本的ulTaskNotifyTake
 (9)xTaskNotifyStateClear清除所有未读消息
三、代码示例
(1)任务通知代替消息队列
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"static void task1(void* param);
static void task2(void* param);static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;int main()
{led_init();portENTER_CRITICAL();   //进入临界区BaseType_t xReturn;/******创建任务1*******/xReturn = xTaskCreate(task1,"task1",128,NULL,2,&task1Handler);if(xReturn==pdTRUE){}/******创建任务2*******/xReturn = xTaskCreate(task2,"task2",128,NULL,2,&task2Handler);if(xReturn==pdTRUE){}portEXIT_CRITICAL();    //退出临界区vTaskStartScheduler();  //开启任务调度器while(1){  }
}//发送消息
void task1(void* param)
{BaseType_t xReturn = pdPASS;uint32_t value1 = 1;uint32_t value2 = 2;while(1){xReturn = xTaskNotify(task2Handler,             //向哪个任务发送通知value1,                   //发送的值eSetValueWithOverwrite);  //写入值方式if(xReturn==pdTRUE){vTaskDelay(1000);}xReturn = xTaskNotify(task2Handler,             //向哪个任务发送通知value2,                   //发送的值eSetValueWithOverwrite);  //写入值方式if(xReturn==pdTRUE){vTaskDelay(1000);}}
}//接收消息
void task2(void* param)
{BaseType_t xReturn;uint32_t recv;while(1){xReturn = xTaskNotifyWait(0x0,                  //进入时要清除的位ULONG_MAX,             //退出时要清除的位,清除所有位&recv,                  //接收的值portMAX_DELAY);        //等待超时时间if(recv == 1 && xReturn==pdTRUE){open();}else if(recv == 2 && xReturn==pdTRUE){close();}}
}(2)任务通知替换二值信号量
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"static void task1(void* param);
static void task2(void* param);static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;int main()
{led_init();portENTER_CRITICAL();   //进入临界区BaseType_t xReturn;/******创建任务1*******/xReturn = xTaskCreate(task1,"task1",128,NULL,2,&task1Handler);if(xReturn==pdTRUE){}/******创建任务2*******/xReturn = xTaskCreate(task2,"task2",128,NULL,2,&task2Handler);if(xReturn==pdTRUE){}portEXIT_CRITICAL();    //退出临界区vTaskStartScheduler();  //开启任务调度器while(1){  }
}//发送消息
void task1(void* param)
{while(1){xTaskNotifyGive(task2Handler);vTaskDelay(500);}
}//接收消息
void task2(void* param)
{static int ledcnt=0;while(1){ulTaskNotifyTake(pdTRUE,portMAX_DELAY);ledcnt=!ledcnt;if(ledcnt==1){open();}else if(ledcnt==0){close();}}
}(3)任务通知代替计数信号量
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"static void task1(void* param);
static void task2(void* param);static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;int main()
{led_init();portENTER_CRITICAL();   //进入临界区BaseType_t xReturn;/******创建任务1*******/xReturn = xTaskCreate(task1,"task1",128,NULL,2,&task1Handler);if(xReturn==pdTRUE){}/******创建任务2*******/xReturn = xTaskCreate(task2,"task2",128,NULL,2,&task2Handler);if(xReturn==pdTRUE){}portEXIT_CRITICAL();    //退出临界区vTaskStartScheduler();  //开启任务调度器while(1){  }
}//发送消息
void task1(void* param)
{while(1){xTaskNotifyGive(task2Handler);vTaskDelay(500);}
}//接收消息
void task2(void* param)
{static int ledcnt=0;uint32_t retu=0;while(1){retu = ulTaskNotifyTake(pdFALSE,0);if(retu==1) ledcnt=!ledcnt;if(ledcnt==1){open();}else if(ledcnt==0){close();}}
}(4)任务通知替代事件组
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "limits.h"static void task1(void* param);
static void task2(void* param);static TaskHandle_t task1Handler;
static TaskHandle_t task2Handler;#define EVENT1 (0x01<<1)
#define EVENT2 (0x01<<2)int main()
{led_init();portENTER_CRITICAL();   //进入临界区BaseType_t xReturn;/******创建任务1*******/xReturn = xTaskCreate(task1,"task1",128,NULL,2,&task1Handler);if(xReturn==pdTRUE){}/******创建任务2*******/xReturn = xTaskCreate(task2,"task2",128,NULL,2,&task2Handler);if(xReturn==pdTRUE){}portEXIT_CRITICAL();    //退出临界区vTaskStartScheduler();  //开启任务调度器while(1){  }
}//发送消息
void task1(void* param)
{while(1){xTaskNotify(task2Handler,EVENT1,eSetBits);//设置任务通知对应位vTaskDelay(500);xTaskNotify(task2Handler,EVENT2,eSetBits);//设置任务通知对应位vTaskDelay(1000);}
}//接收消息
void task2(void* param)
{    uint32_t recv;while(1){xTaskNotifyWait(0x0,ULONG_MAX,&recv,portMAX_DELAY);if(recv == EVENT1){//事件或open();}else if(recv == EVENT2){close();}}
}