2026/4/6 9:28:54
网站建设
项目流程
卓训网是个什么网站,网站改版需求分析,网站开发报价范围,wordpress开放多站点消息量信号量本质上是一个特殊的队列#xff0c;但是它内部是一个计数装置#xff0c;通过计数来表明程序的状态#xff0c;可以理解成一个状态机#xff0c;信号量是FreeRTOS中用于计数和同步的工具#xff0c;主要解决#xff1a;1个资源多个任…消息量信号量本质上是一个特殊的队列但是它内部是一个计数装置通过计数来表明程序的状态可以理解成一个状态机信号量是FreeRTOS中用于计数和同步的工具主要解决1个资源多个任务抢的问题和1个事件多个任务等的问题。信号量的使用主要分为创建读取释放三个步骤此外还有一个删除操作创建信号量使用信号量之前要先创建得到一个句柄使用信号量时要使用句柄来表明使用哪个信号量。 对于二进制信号量、计数型信号量它们的创建函数不一样具体的信号量还分为二进制信号量和计数信号量他两个大致的区别就是二进制初始数据只能是1技术型可以自己设定此外还有动态和静态之分动态和静态的区别前面已经说过这个里就直接搬运韦老师的代码了/* 创建一个二进制信号量返回它的句柄。 * 此函数内部会分配信号量结构体 * 返回值: 返回句柄非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateBinary( void ); /* 创建一个二进制信号量返回它的句柄。 * 此函数无需动态分配内存所以需要先有一个StaticSemaphore_t结构体并传入它的指针 * 返回值: 返回句柄非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer ); 创建计数型信号量的函数原型如下 /* 创建一个计数型信号量返回它的句柄。 * 此函数内部会分配信号量结构体 * uxMaxCount: 最大计数值 * uxInitialCount: 初始计数值 * 返回值: 返回句柄非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount); /* 创建一个计数型信号量返回它的句柄。 * 此函数无需动态分配内存所以需要先有一个StaticSemaphore_t结构体并传入它的指针 * uxMaxCount: 最大计数值 * uxInitialCount: 初始计数值 * pxSemaphoreBuffer: StaticSemaphore_t结构体指针 * 返回值: 返回句柄非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer );然后是读取函数这个函数有任务中和中断中两种在任务中使用在ISR中使用givexSemaphoreGivexSemaphoreGiveFromISRxSemaphoreGive的函数原型如下BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );xSemaphoreGive函数的参数与返回值列表如下参数说明xSemaphore信号量句柄释放哪个信号量返回值pdTRUE表示成功, 如果二进制信号量的计数值已经是1再次调用此函数则返回失败 如果计数型信号量的计数值已经是最大值再次调用此函数则返回失败pxHigherPriorityTaskWoken的函数原型如下BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );xSemaphoreGiveFromISR函数的参数与返回值列表如下参数说明xSemaphore信号量句柄释放哪个信号量pxHigherPriorityTaskWoken如果释放信号量导致更高优先级的任务变为了就绪态 则*pxHigherPriorityTaskWoken pdTRUE返回值pdTRUE表示成功, 如果二进制信号量的计数值已经是1再次调用此函数则返回失败 如果计数型信号量的计数值已经是最大值再次调用此函数则返回失败然后是释放xSemaphoreTake的函数原型如下BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );xSemaphoreTake函数的参数与返回值列表如下参数说明xSemaphore信号量句柄获取哪个信号量xTicksToWait如果无法马上获得信号量阻塞一会 0不阻塞马上返回 portMAX_DELAY: 一直阻塞直到成功 其他值: 阻塞的Tick个数可以使用*pdMS_TO_TICKS()*来指定阻塞时间为若干ms返回值pdTRUE表示成功xSemaphoreTakeFromISR的函数原型如下BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );xSemaphoreTakeFromISR函数的参数与返回值列表如下参数说明xSemaphore信号量句柄获取哪个信号量pxHigherPriorityTaskWoken如果获取信号量导致更高优先级的任务变为了就绪态 则*pxHigherPriorityTaskWoken pdTRUE返回值pdTRUE表示成功最后是删除操作对于动态创建的信号量不再需要它们时可以删除它们以回收内存。vSemaphoreDelete可以用来删除二进制信号量、计数型信号量函数原型如下/* * xSemaphore: 信号量句柄你要删除哪个信号量 */ void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );然后我来给大家将几点注意事项1.如果你的代码不是事先用CUBEMX生成好的信号量那么你就需要引用#include semphr.h头文件2.一定有释放要不然又溢出风险这种一般是不会编译报错的但是运行不出来结果然后我们在使用信号量可能会出现优先级反转的问题简单来说就是低优先级的任务运行比高优先级的任务高这个原因就是因为信号量的权限一直在低优先级手里也就是低优先级没有释放信号量造成的大概如图所示要想完美解决这个问题就要使用到互斥量