计数型信号量
计数型信号量相当于队列长度大于1 的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的
计数型信号量适用场合:
- 事件计数:当每次事件发生后,在事件处理函数中释放计数型信号量(计数值+1),其他任务 会获取计数型信号量(计数值-1) ,这种场合一般在创建时将初始计数值设置为 0
- 资源管理:信号量表示有效的资源数目。任务必须先获取信号量(信号量计数值-1 )才能获取资源控制权。当计数值减为零时表示没有的资源。当任务使用完资源后,必须释放信号量(信号量计数值+1)。信号量创建时计数值应等于最大资源数目
计数型信号量相关API函数
使用计数型信号量的过程:创建计数型信号量 释放信号量
获取信号量
函数 | 描述 |
xSemaphoreCreateCounting() | 使用动态方法创建计数型信号量。 |
xSemaphoreCreateCountingStatic() | 使用静态方法创建计数型信号量 |
uxSemaphoreGetCount() | 获取信号量的计数值 |
计数型信号量的释放和获取与二值信号量相同 !
计数型信号量创建API函数
此函数用于创建一个计数型信号量 。
#define xSemaphoreCreateCounting ( uxMaxCount , uxInitialCount) \
xQueueCreateCountingSemaphore((uxMaxCount) , (uxInitialCount))
形参 | 描述 |
uxMaxCount | 计数值的最大值限定 |
uxInitialCount | 计数值的初始值 |
返回值 | 描述 |
NULL | 创建失败 |
其他值 | 创建成功返回计数型信号量的句柄 |
获取信号量的计数值API函数
此函数用于获取信号量当前计数值大小。
#define uxSemaphoreGetCount ( xSemaphore ) \
uxQueueMessagesWaiting(( QueueHandle_t) (xSemaphore))
形参 | 描述 |
xSemaphore | 信号量句柄 |
返回值 | 描述 |
整数 | 当前信号量的计数值大小 |
计数型信号量实验
实验目的:学习 FreeRTOS 的计数型信号量相关API函数的使用
实验设计:将设计三个任务:start_task、task1、task2
三个任务的功能如下:
- start_task:用来创建其他的2个任务
- task1:用于按键扫描,当检测到按键KEY0被按下时,释放计数型信号量
- task2:每过一秒获取一次计数型信号量,当成功获取后打印信号量计数值
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
SemaphoreHandle_t CountSemaphore; /* 计数型信号量 */
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建计数型信号量 */
CountSemaphore = xSemaphoreCreateCounting((UBaseType_t )255,/* 计数型信号量最大值 */
(UBaseType_t )0); /* 计数型信号量初始值 */
if(CountSemaphore != NULL)
{
printf("计数型信号量创建成功\r\n");
}
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
BaseType_t respond;
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES)
{
respond = xSemaphoreGive(CountSemaphore); /* 释放计数型信号量 */
if(respond == pdTRUE)
{
printf("释放计数型信号量成功\r\n");
}
else printf("释放计数型信号量失败\r\n");
}
vTaskDelay(10);
}
}
void task2(void *pvParameters)
{
UBaseType_t semaphore_val = 0;
BaseType_t respond;
while (1)
{
respond = xSemaphoreTake(CountSemaphore, portMAX_DELAY); /* 获取计数型信号量 */
if(respond == pdTRUE)
{
printf("获取计数型信号量成功\r\n");
}
else printf("获取计数型信号量失败\r\n");
semaphore_val = uxSemaphoreGetCount(CountSemaphore);/* 获取计数型信号量资源数 */
printf("获取计数型信号量资源数为:%ld\r\n",semaphore_val);
vTaskDelay(1000);
}
}
造成上图的原因是 任务调度。本次实验仅涉及普通演示,如果想要深究可以看下面这篇,能解惑。