計數型信号量簡介:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90TUaxWOxkVNk1mYwJlMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4cTOzMTN1ITMwMTMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
計數型信号量的建立:
計數型信号量動态建立函數:
釋放和擷取信号量(與二值信号量相同)
釋放信号量:
擷取信号量:
測試實驗
用按鍵來模拟事件,按鍵按下後表示有事件發生,則釋放計數型信号量。
建立兩個任務,任務1用于按鍵檢測和釋放信号量,按鍵2用于擷取信号量。
測試程式如下所示:
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
count_semphr = xSemaphoreCreateCounting(5, 0);
if (count_semphr != NULL)
{
printf("計數型信号量建立成功\n");
}
else
{
printf("計數型信号量建立失敗\n");
}
// 建立任務1
xTaskCreate((TaskFunction_t ) task1_task,
(char * ) "task1_task",
(uint16_t ) TASK1_TASK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_TASK_PRIO,
(TaskHandle_t * ) &Task1_Handle);
// 建立任務2
xTaskCreate((TaskFunction_t )task2_task,
(char * )"task2_task",
(uint16_t )TASK2_TASK_SIZE,
(void * )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t * )&Task2_Handle);
taskEXIT_CRITICAL();
// 删除開始任務
vTaskDelete(Start_Task_Handle);
}
void task1_task(void *pvParameters)
{
BaseType_t error_state;
for (;;)
{
// 按鍵KEY1用于釋放信号量
if (key_scan(KEY1_GPIO_Port, KEY1_Pin) == KEY_ON)
{
if (count_semphr != NULL)
{
error_state = xSemaphoreGive(count_semphr);
if (error_state == pdTRUE)
{
printf("信号量釋放成功\n");
}
else
{
printf("信号量釋放失敗\n");
}
}
}
vTaskDelay(20);
}
}
void task2_task(void *pvParameters)
{
BaseType_t error_state;
UBaseType_t current_semphr_value;
for (;;)
{
// 按鍵KEY2用于擷取信号量
if (key_scan(KEY2_GPIO_Port, KEY2_Pin) == KEY_ON)
{
if (count_semphr != NULL)
{
// 等待擷取信号量
error_state = xSemaphoreTake(count_semphr, portMAX_DELAY);
if (error_state == pdTRUE)
{
printf("擷取信号量成功\n");
current_semphr_value = uxSemaphoreGetCount(count_semphr);
printf("目前信号量計數值為%d\n", (int)current_semphr_value);
}
else
{
printf("擷取信号量失敗\n");
}
}
}
vTaskDelay(50);
}
}
測試結果: