FREERTOS_任务通知——使用

目录

一、特点

二、使用流程(无 “创建” 步骤,直接用任务句柄)

1. 前置准备(已经有一个可以run的任务,下面这些得有)

2. 创建发送 / 接收任务

三、基本使用(核心 API 与操作)

1. 发送通知(发送任务调用)

2. 接收通知(接收任务调用)

四、接收和发送加一个简单的校验,这里以LED为例:

1、main外的:

2、我有创建的两个任务:

任务1、

任务2、这个函数读取不同的按键来发不同的任务通知


一、特点

  • 无需创建独立句柄:通过任务句柄直接发送 / 接收通知,省内存;
  • 32 位通知内容:可存储命令、参数、状态等(灵活传递少量数据);
  • 支持多模式:覆盖、叠加、置位等,适配不同场景;
  • 替代简单队列 / 信号量:适合 “任务→任务” 的一对一 / 一对多通信。

二、使用流程(无 “创建” 步骤,直接用任务句柄)

1. 前置准备(已经有一个可以run的任务,下面这些得有)

   包含头文件

#include "FreeRTOS.h"
#include "task.h" // 任务通知API在task.h中声明

   定义接收任务的句柄

TaskHandle_t xRecvTaskHandle = NULL; // 接收通知的任务句柄
2. 创建发送 / 接收任务

通过xTaskCreate()创建两个任务(发送方和接收方),并保存接收任务的句柄:

// 创建接收任务(保存句柄)
xTaskCreate(RecvTask, "RecvTask", 128, NULL, 1, &xRecvTaskHandle);
// 创建发送任务
xTaskCreate(SendTask, "SendTask", 128, NULL, 2, NULL);

三、基本使用(核心 API 与操作)

1. 发送通知(发送任务调用)

        在任务中:xTaskNotify()发送 32 位通知内容,关键是指定 “接收任务句柄” 和 “通知模式”:

uint32_t ulNotifyValue = 0x12345678; // 32位通知内容(可存命令+参数)

// 发送通知(核心函数)
xTaskNotify(
  xRecvTaskHandle,        // 接收通知的任务句柄(必须有效)
  ulNotifyValue,          // 要发送的32位内容
  eSetValueWithOverwrite  // 通知模式(常用3种,见下表)
);

常用的通知模式:

模式作用适用场景
eSetValueWithOverwrite新通知覆盖旧通知(仅保留最新值)传递实时参数(如闪烁频率)
eSetValueWithoutOverwrite旧通知未处理则不覆盖(防止丢失)传递事件(如按键触发)
eSetBits按位叠加(仅置 1 对应位,不清除其他位)多事件标记(如多个按键)
2. 接收通知(接收任务调用)

        在任务中:xTaskNotifyWait()等待并接收通知,可设置 “阻塞超时” 和 “位操作”:

参数定义放任务起始:

uint32_t ulRecvValue; // 存储接收的32位通知内容
BaseType_t xResult;   // 接收结果(pdPASS=成功)

接收的代码:

// 接收通知(核心函数)
xResult = xTaskNotifyWait(
  0xFFFFFFFFU,        // 接收后要清除的位(0xFFFFFFFF=清除所有位)
  0xFFFFFFFFU,        // 接收时要保留的位(0xFFFFFFFF=保留所有位)
  &ulRecvValue,       // 存储接收内容的指针
  portMAX_DELAY       // 阻塞超时时间(0=非阻塞,portMAX_DELAY=永久等待)
);

// 处理通知
if(xResult == pdPASS) {
  // 解析ulRecvValue(如命令+参数分离)
  uint16_t cmd = (ulRecvValue >> 16) & 0xFFFF; // 高16位为命令
  uint16_t param = ulRecvValue & 0xFFFF;       // 低16位为参数
}

四、接收和发送加一个简单的校验,这里以LED为例:

通过位运算检查高 16 位的 “命令标识”:

为什么用高 16 位做命令?

        避免参数值和命令冲突(比如参数最大是 65535,不会影响高 16 位);

为什么用固定命令值?

        唯一标识通知的用途(比如后续扩展CMD_SET_COLOR控制 LED 颜色,也用高 16 位区分)。

1、main外的:
// 任务通知内容定义(用32位值传递:高16位标识命令,低16位传递参数)
#define CMD_SET_DELAY       0x00010000U // 命令:设置LED延时
#define GET_DELAY_PARAM(x)  (x & 0xFFFFU) // 提取低16位的延时参数
2、我有创建的两个任务:
//外:
osThreadId_t LED_TaskHandle;
const osThreadAttr_t LED_Task_attributes = {
  .name = "LED_Task",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityBelowNormal7,
};

osThreadId_t KEY_TaskHandle;
const osThreadAttr_t KEY_Task_attributes = {
  .name = "KEY_Task",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
void Start_LED_Task(void *argument);
void Start_KEY_Task(void *argument);


//内:
LED_TaskHandle = osThreadNew(Start_LED_Task, NULL, &LED_Task_attributes);
KEY_TaskHandle = osThreadNew(Start_KEY_Task, NULL, &KEY_Task_attributes);
任务1、
void Start_LED_Task(void *argument)
{
  uint32_t ulNotificationValue; // 接收的通知内容
  uint16_t current_delay = 500U; // 默认500ms闪烁
  BaseType_t xResult;

  // 初始状态:确保LED是熄灭的(可选,根据硬件调整)
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
  for(;;)
  { //HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_10);
    /* 核心修改:用 xTaskNotifyWait 替代 xTaskNotifyWaitIndexed(基础API) */
    xResult = xTaskNotifyWait(
      0xFFFFFFFFU,        // 接收后清除所有位(清空通知)
      0xFFFFFFFFU,        // 保留所有位(完整接收32位内容)
      &ulNotificationValue, // 存储通知内容
      0  //portMAX_DELAY       // 永久等待通知
    );

    /* 收到通知后解析处理 */
    if(xResult == pdPASS)
    {
      // 判断是否是“设置延时”命令
      if((ulNotificationValue & 0xFFFF0000U) == CMD_SET_DELAY)
      {
        current_delay = GET_DELAY_PARAM(ulNotificationValue); // 更新延时
      }
    }

    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    vTaskDelay(current_delay); // ѓʱ500ms
  }
}
任务2、这个函数读取不同的按键来发不同的任务通知
    case 1:
		// 构造通知:命令 + 延时参数
        ulNotificationValue = CMD_SET_DELAY | 200U;
        // 核心修改:用 xTaskNotify 替代 xTaskNotifyGiveIndexed(基础API,无索引)
        //             接收通知的任务句柄、通知内容、覆盖模式:新通知替换旧通知
        xTaskNotify(LED_TaskHandle, ulNotificationValue,eSetValueWithOverwrite);        
        ); 
    break;

    case 2:
		ulNotificationValue = CMD_SET_DELAY | 800U;
        xTaskNotify(LED_TaskHandle, ulNotificationValue, eSetValueWithOverwrite);
    break;

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值