什么是信号量?
信号量(Semaphore),是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代 码段不被并发调用。 信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用,然后我们的量还可以 用来表示资源的数量,
当我们的量只有0和1的时候,它就可以被称作二值信号量,只有两个状 态,当我们的那个量没有限制的时候,它就可以被称作为计数型信号量。 信号量也是队列的一种。 什么是二值信号量?
二值信号量其实就是一个长度为1,大小为零的队列,只有0和1两种状态,通常情况下,我们用 它来进行互斥访问或任务同步。
互斥访问:比如门钥匙,只有获取到钥匙才可以开门
任务同步:比如我录完视频你才可以看视频
1. 创建二值信号量
SemaphoreHandle_t xSemaphoreCreateBinary( void )
参数: 无
返回值: 成功,返回对应二值信号量的句柄; 失败,返回 NULL 。
2. 释放二值信号量
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore )
参数: xSemaphore:要释放的信号量句柄
返回值: 成功,返回 pdPASS ; 失败,返回 errQUEUE_FULL 。
3、获取二值信号量
seType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
参数: xSemaphore:要获取的信号量句柄
xTicksToWait:超时时间,0 表示不超时,
portMAX_DELAY表示卡死等待;
返回值: 成功,返回 pdPASS ; 失败,返回 errQUEUE_FULL 。
实操 实验需求 创建一个二值信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。
代码:
myBinarySemHandle = xSemaphoreCreateBinary();
void StartTaskGive(void const * argument)
{
/* USER CODE BEGIN StartTaskGive */
/* Infinite loop */
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( myBinarySemHandle)==pdTRUE)
printf("二值信号量放入成功\r\n");
else
printf("二值信号量放入失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
}
osDelay(10);
}
/* USER CODE END StartTaskGive */
}
/* USER CODE BEGIN Header_StartTaskTake */
/**
* @brief Function implementing the taskTake thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskTake */
void StartTaskTake(void const * argument)
{
/* USER CODE BEGIN StartTaskTake */
/* Infinite loop */
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(myBinarySemHandle,portMAX_DELAY)==pdTRUE)
printf("取出二值信号量成功\r\n");
else
printf("取出二值信号量失败\r\n");
}
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
}
osDelay(10);
}
/* USER CODE END StartTaskTake */
}