新闻详情

新闻详情

首页 / 资讯中心 / 详情

RTOS中的任务通知

发布时间:2026/9/1 17:00:53来源:尧图网络
RTOS中的任务通知
任务通知之前我们使用队列、信号量、事件组等方法来控制任务在这个过程当中我们都需要实现创建对应的结构体双方通过结构体来进行交流。同时我们还可以使用任务通知的方式来进行控制。优势效率更高使用任务通知来发送事件、数据给某个任务时效率更高。比队列、信号量、事件组都有大的优势。更节省内存使用其他方法时都要先创建对应的结构体使用任务通知时无需额外创建结构缺点不能发送数据给 ISR因为ISR没有任务结构体但是ISR可以使用任务通知的功能数据只能该任务独享无法缓冲数据任务结构体只有一个任务通知值只能保持一个数据无法广播给多个任务任务通知可以多对一但不能一对多如果发送受阻发送方不会进入阻塞状态等待对应代码已知任务都有对应的结构体TCB里面的两个数据一个是 uint8_t 类型用来表示通知状态一个是 uint32_t 类型用来表示通知值typedef struct tskTaskControlBlock { ...... /* configTASK_NOTIFICATION_ARRAY_ENTRIES 1 */ volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; ...... } tskTCB;其中的ucNotifyState有3种取值taskNOT_WAITING_NOTIFICATION任务没有在等待通知taskWAITING_NOTIFICATION任务在等待通知taskNOTIFICATION_RECEIVED任务接收到了通知也被称为 pending(有数据了待处理)任务通知的使用任务通知函数主要分为简化版和专业版简化版专业版发出通知xTaskNotifyGivevTaskNotifyGiveFromISRxTaskNotifyxTaskNotifyFromISR取出通知ulTaskNotifyTakexTaskNotifyWait简化版其中简化版当中发出通知可以使TCB当中的val加一并使通知状态变为pending取出通知则需要判断val的值如果为0则阻塞大于0则从阻塞态进入就绪态。函数原型BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTa skWoken ); uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );主要讲解一下Take函数中参数的含义参数说明xClearCountOnExit函数返回前是否清零pdTRUE把通知值清零pdFALSE如果通知值大于 0则把通知值减一xTicksToWait任务进入阻塞态的超时时间它在等待通知值大于 0。0不等待即刻返回portMAX_DELAY一直等待直到通知值大于 0其他值Tick Count可以用 pdMS_TO_TICKS()把 ms 转换为 Tick Count返回值函数返回之前在清零或减一之前的通知值。如果 xTicksToWait 非 0则返回值有 2 种情况1. 大于 0在超时前通知值被增加了2. 等于 0一直没有其他任务增加通知值最后超时返回 0专业版xTaskNotify 函数功能更强大可以使用不同参数实现各类功能。BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyActio n eAction ); BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );案例整体思路先让小车1动然后到达终点后同时2和3分别使用xTaskNotifyGive 和 xTaskNotify。小车1static void Car1Task (void *params) { struct car *car (struct car *) params; //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 发送事件 */ //xEventGroupSetBits(g_xEventCar, 10); //发出通知 xTaskNotifyGive(g_TaskHandleCar2); xTaskNotify(g_TaskHandleCar3, 100, eSetValueWithOverwrite); vTaskDelete(NULL); } } }小车2static void Car2Task (void *params) { struct car *car (struct car *) params; //等待事件信号 //xEventGroupWaitBits(g_xEventCar, 1 0, pdTRUE, pdFALSE, portMAX_DELAY); //等待通知 ulTaskNotifyTake(pdTRUE, portMAX_DELAY); //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 释放信号量 */ // xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } }完整代码/* * Project: N|Watch * Author: Zak Kemble, contactzakkemble.co.uk * Copyright: (C) 2013 by Zak Kemble * License: GNU GPL v3 (see License.txt) * Web: http://blog.zakkemble.co.uk/diy-digital-wristwatch/ */ #include stdlib.h #include stdio.h #include string.h #include cmsis_os.h #include FreeRTOS.h // ARM.FreeRTOS::RTOS:Core #include task.h // ARM.FreeRTOS::RTOS:Core #include event_groups.h // ARM.FreeRTOS::RTOS:Event Groups #include semphr.h // ARM.FreeRTOS::RTOS:Core #include draw.h #include resources.h #include driver_lcd.h #include driver_ir_receiver.h #include driver_rotary_encoder.h #include driver_mpu6050.h #define CAR_COUNT 3 #define CAR_WIDTH 12 #define CAR_LENGTH 15 #define ROAD_SPEED 6 #define NOINVERT false #define INVERT true #define key1 0 #define key2 1 #define key3 2 static uint32_t g_xres, g_yres, g_bpp; static uint8_t *g_framebuffer; static SemaphoreHandle_t g_xSemTicks; static EventGroupHandle_t g_xEventCar; static TaskHandle_t g_TaskHandleCar2; static TaskHandle_t g_TaskHandleCar3; struct car{ int x; int y; int control_key; }; struct car cars[3] { {0, 0, key1}, {0, 17, key2}, {0, 34, key3} }; static const byte carImg[] PROGMEM { 0x40,0xF8,0xEC,0x2C,0x2C,0x38,0xF0,0x10,0xD0,0x30,0xE8,0x4C,0x4C,0x9C,0xF0, 0x02,0x1F,0x37,0x34,0x34,0x1C,0x0F,0x08,0x0B,0x0C,0x17,0x32,0x32,0x39,0x0F, }; static const byte roadMarking[] PROGMEM { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, }; static const byte clearImg[30] {0}; static void showCar(struct car *car) { draw_bitmap(car-x, car-y, carImg, 15, 16, NOINVERT, 0); draw_flushArea(car-x, car-y, 15, 16); } static void hideCar(struct car *car) { draw_bitmap(car-x, car-y, clearImg, 15, 16, NOINVERT, 0); draw_flushArea(car-x, car-y, 15, 16); } # if 0 static void CarTask(void *params) { struct car *car (struct car *)params; //获得信号量 xSemaphoreTake(g_xSemTicks, portMAX_DELAY); while(1) { if(car-x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car-x g_xres - CAR_LENGTH) { /* 释放信号量 */ xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } } #endif static void Car1Task (void *params) { struct car *car (struct car *) params; //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 发送事件 */ //xEventGroupSetBits(g_xEventCar, 10); //发出通知 xTaskNotifyGive(g_TaskHandleCar2); xTaskNotify(g_TaskHandleCar3, 100, eSetValueWithOverwrite); vTaskDelete(NULL); } } } static void Car2Task (void *params) { struct car *car (struct car *) params; //等待事件信号 //xEventGroupWaitBits(g_xEventCar, 1 0, pdTRUE, pdFALSE, portMAX_DELAY); //等待通知 ulTaskNotifyTake(pdTRUE, portMAX_DELAY); //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 释放信号量 */ // xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } } static void Car3Task (void *params) { struct car *car (struct car *) params; //等待事件信号 //xEventGroupWaitBits(g_xEventCar, 1 0, pdTRUE, pdFALSE, portMAX_DELAY); int val; xTaskNotifyWait(~0, ~0, val, portMAX_DELAY); //直接右移小汽车 while(1) { if(car - x g_xres - CAR_LENGTH) { hideCar(car); car-x 1; if (car-x g_xres - CAR_LENGTH) { car-x g_xres - CAR_LENGTH; } showCar(car); } vTaskDelay(50); if(car -x g_xres - CAR_LENGTH) { /* 释放信号量 */ //xSemaphoreGive(g_xSemTicks); vTaskDelete(NULL); } } } void car_test(void) { g_framebuffer LCD_GetFrameBuffer(g_xres, g_yres, g_bpp); draw_init(); draw_end(); //绘制路标 for(int i 0; i 3; i) { for(int j 0; j 8; j) { draw_bitmap(16 * j, 16 i * 17, roadMarking, 8, 1, NOINVERT, 0); draw_flushArea(16 * j, 16 i * 17, 8, 1); } } //测试显示三辆汽车 for(int i 0; i 3; i) { showCar(cars[i]); } /* g_xSemTicks xSemaphoreCreateCounting(3, 2); xTaskCreate(CarTask, Car1, 128, cars[0], osPriorityNormal, NULL); xTaskCreate(CarTask, Car2, 128, cars[1], osPriorityNormal, NULL); xTaskCreate(CarTask, Car3, 128, cars[2], osPriorityNormal, NULL); */ //创建事件组 //g_xEventCar xEventGroupCreate(); xTaskCreate(Car1Task, car1, 128, cars[0], osPriorityNormal, NULL); xTaskCreate(Car2Task, car2, 128, cars[1], osPriorityNormal2, g_TaskHandleCar2); xTaskCreate(Car3Task, car3, 128, cars[2], osPriorityNormal2, g_TaskHandleCar3); }
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

2026博士论文初稿怎么写?六款工具横向测评清单 2026/9/1 18:46:23

2026博士论文初稿怎么写?六款工具横向测评清单

博士论文季一到,图书馆通宵区又坐满了人。开题报告过了、文献读了上百篇,真到动笔写初稿那一刻,光标在空白文档里闪了半小时,一个字没敲出来。这种卡壳感我太熟了——初稿写作的难点从来不是“不会写”,而是“从哪写起…

阅读更多 →
2026毕业论文AI辅助红黑榜:选错真会延毕 2026/9/1 18:46:23

2026毕业论文AI辅助红黑榜:选错真会延毕

每年毕业季,总有人因为论文工具选错,进度一拖再拖,最后卡在查重或AI检测上。这篇红黑榜基于实际体验整理,帮26届毕业生避开那些看着省心、实则添堵的选项。 黑榜先行:这三类工具千万别碰 只生成不修改的一次性工具 …

阅读更多 →
从拼写歌词看内容传播机制:如何用认知缺口撬动用户参与 2026/9/1 18:46:23

从拼写歌词看内容传播机制:如何用认知缺口撬动用户参与

我刷到一条Treasure的粉丝动态,标题里那句“D to the E, to the L-I-C-I-O-U-S”直接把我看愣了。把它拼出来就是delicious,但那行字真正吸引我的,不是英文单词,而是后面跟着的括号注解:“孩子们知道歌词吗&#xff0c…

阅读更多 →
2026毕业论文自动生成工具盘点:这几款值得关注 2026/9/1 18:46:23

2026毕业论文自动生成工具盘点:这几款值得关注

毕业论文从开题到定稿,战线拖上大半年是常态。选题被导师驳回、文献综述写到怀疑人生、查重率居高不下——这些场景每个毕业生都不陌生。市场上打着"论文自动生成"旗号的工具越来越多,但真正能解决问题的有多少?这篇文章把当前主流…

阅读更多 →
2026毕业论文一条龙服务怎么选?实测四款工具再下结论 2026/9/1 18:46:23

2026毕业论文一条龙服务怎么选?实测四款工具再下结论

毕业论文季一到,宿舍楼里熬夜的人明显多了。从选题到定稿,文献检索、框架搭建、内容撰写、降重降AI、格式调整,每个环节都能卡住一批人。市面上的毕业论文一条龙服务五花八门,但实际体验差距不小。我花了三周时间,把四…

阅读更多 →
pstack验证技能:让AI Agent像真实用户一样验证应用 2026/9/1 18:43:23

pstack验证技能:让AI Agent像真实用户一样验证应用

pstack 这次新增的能力,把“验证”这件事从脚本层提成了“技能层”。过去我们让 Agent 验证应用,要么写死一段测试脚本,要么靠模型现场“自由发挥”,结果经常是:会点、会填,但不知道结果对不对,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞