什么是计数型信号量?
计数型信号量相当于队列长度大于1 的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的。
使用计数型信号量可以解决多个任务之间的同步问题,例如控制对共享资源的访问和协调任务的执行顺序。
计数型信号量相关 API 函数
函数 | 描述 |
xSemaphoreCreateCounting() | 使用动态方法创建计数型信号量 |
xSemaphoreCreateCountingStatic() | 使用静态方法创建计数型信号量 |
uxSemaphoreGetCount() | 获取信号量的计数值 |
1. 创建计数型信号量
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);
参数:
uxMaxCount:可以达到的最大计数值 uxInitialCount:创建信号量时分配给信号量的计数值
返回值:
成功,返回对应计数型信号量的句柄;
失败,返回 NULL 。
2. 释放二值信号量
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore )
参数:
xSemaphore:要释放的信号量句柄
返回值:
- 成功,返回 pdPASS ;
- 失败,返回 errQUEUE_FULL 。
3. 获取二值信号量
1. BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, 2. TickType_t xTicksToWait );
参数:
- xSemaphore:要获取的信号量句柄
- xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;
返回值:
- 成功,返回 pdPASS ;
- 失败,返回 errQUEUE_FULL 。
计数型信号量实操
1.打开CubeMX,将FreeRTOS移植到STM32F103C8T6,具体看我之前写过的文章
2.然后创建两个任务和设置按键引脚为输入,通过按键来放入和获取信号量
3.使能计数信号量
4.创建一个计数信号量,设置最多存放3个信号量,导出代码
5.进行代码编写
freertos.c
void StartTaskKey1(void const * argument) { for(;;) { if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { osDelay(20); if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { if(xSemaphoreGive(myCountingSem01Handle) == pdTRUE) printf("计数型信号量放入成功\r\n"); else printf("计数型信号量放入失败\r\n"); } while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); } osDelay(10); } } void StartTaskKey2(void const * argument) { for(;;) { if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET) { osDelay(20); if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET) { if(xSemaphoreTake(myCountingSem01Handle,0) == pdTRUE) printf("计数型信号量获取成功\r\n"); else printf("计数型信号量获取失败\r\n"); } while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET); } osDelay(10); } }
6.编译烧录程序后打开串口助手(默认初始化已经放入3个信号量)