【FreeRTOS篇】信号量

一、二值信号量

1.什么是信号量?

信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用,然后我们的量还可以用来表示资源的数量,当我们的量只有0和1的时候,它就可以被称作二值信号量,只有两个状态,当我们的那个量没有限制的时候,它就可以被称作为计数型信号量。

信号量也是队列的一种。

2.什么是二值信号量?

二值信号量其实就是一个长度为1,大小为零的队列,只有0和1两种状态,通常情况下,我们用它来进行互斥访问或任务同步。

互斥访问:比如门钥匙,只有获取到钥匙才可以开门任务同步:比如录完视频你才可以看视频。

3.二值信号量相关 API 函数

(1) 创建二值信号量

SemaphoreHandle_t xSemaphoreCreateBinary( void );

参数:
无
返回值:
成功,返回对应二值信号量的句柄;
失败,返回 NULL 。

(2)释放二值信号量

BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

参数:
xSemaphore:要释放的信号量句柄
返回值:
成功,返回 pdPASS ;
失败,返回 errQUEUE_FULL 。

(3)获取二值信号量

BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,
                            TickType_t xTicksToWait );

参数:
xSemaphore:要获取的信号量句柄
xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;
返回值:
成功,返回 pdPASS ;失败,返回 errQUEUE_FULL 。

4.实操

•实验需求:创建一个二值信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

•编程实现

myBinarySemHandle = xSemaphoreCreateBinary();
void StartTaskGive(void const * argument)
{
  /* USER CODE BEGIN StartTaskGive */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
			{
				if(xSemaphoreGive(myBinarySemHandle) == pdTRUE)
				{
					printf("二值信号量放入成功\r\n");
				}
				else
				{
					printf("二值信号量放入失败\r\n");
				}
			}	
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskGive */
}

void StartTaskTake(void const * argument)
{
  /* USER CODE BEGIN StartTaskTake */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET)
			{
				if(xSemaphoreTake(myBinarySemHandle,portMAX_DELAY) == pdTRUE)
				{
					printf("二值信号量获取成功\r\n");
				}
				else
				{
					printf("二值信号量获取失败\r\n");
				}
			}	
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskTake */
}

二、计数型信号量

1.什么是计数型信号量?

计数型信号量相当于队列长度大于1 的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的。

2.计数型信号量相关 API 函数

(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)获取计数型信号量

BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,
                            TickType_t xTicksToWait );

参数:
xSemaphore:要获取的信号量句柄
xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;
返回值:
成功,返回 pdPASS ;失败,返回 errQUEUE_FULL 。

3.实操

•实验需求:创建一个计数型信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

•cubeMX配置

先将 Config parameters 标签里的 USE_COUNTING_SEMAPHORES 设置为 Enabled 。

•编程实现

myCountingSemHandle = xSemaphoreCreateCounting(3,0);
void StartTaskGive(void const * argument)
{
  /* USER CODE BEGIN StartTaskGive */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
			{
				if(xSemaphoreGive(myCountingSemHandle) == pdTRUE)
				{
					printf("计数值信号量放入成功\r\n");
				}
				else
				{
					printf("计数值信号量放入失败\r\n");
				}
			}	
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskGive */
}

void StartTaskTake(void const * argument)
{
  /* USER CODE BEGIN StartTaskTake */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET)
			{
				if(xSemaphoreTake(myCountingSemHandle,0) == pdTRUE)
				{
					printf("计数值信号量获取成功\r\n");
				}
				else
				{
					printf("计数值信号量获取失败\r\n");
				}
			}	
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskTake */
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿gao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值