一,信号量
有时候任务之间传递的只是一个标致,让进程之间同步,会对一个共享资源的互斥性访问,这时候就可以用信号量和互斥量。

1,二值信号量

2,计数信号量

3,互斥量
3.1,差别

4,递归互斥量
递归互斥量(Recursive Mutex)是一种特殊的互斥量,可以用于需要递归调用的函数中。
一个任务在获得了互斥量之后就不能再获得互斥量,而一个任务获得递归互斥量之后,可以再次获得此递归互斥量,当然每次获取必须与一次释放配对使用。
递归互斥量同样不能在ISR函数中使用
二,相关的函数定义
在semphr.h中
创立和删除
发送和接收
三,Demo:
1,二值信号量
定时器中断进行周期为500ms的ADC采集,在ISR里将转化结果写入缓存变量,并且释放信号量,任务中总是尝试获取信号量,获取到之后读取ADC的值,在OLED上显示。
//任务
void AppTask_Oled_Display(void *argument)
{
  /* USER CODE BEGIN AppTask_Oled_Display */
	KEYS KeyValue;
	/* Infinite loop */
	for (;;) {
        //获取信号量
		if(xSemaphoreTake(BinSem_AdcReadyHandle, portMAX_DELAY) == pdTRUE)
		{
			OLED_Printf(0, 1, 6, "ADC_Value=");
			OLED_ShowDecNum(60, 1, ADC_Value, 5, 6);
			OLED_Printf(0, 2, 6, "Voltage=");
			OLED_ShowDecNum(60, 2, ADC_Value/4095*3300, 5, 6);
		}
		if(xQueueReceive(Queue_KeysHandle, &KeyValue, pdMS_TO_TICKS(50)) != pdTRUE){continue;}
		if(KeyValue == KEY0){
			OLED_Printf(90, 0, 6, "Key=0");
		}else if(KeyValue == KEY1){
			OLED_Printf(90, 0, 6, "Key=1");
		}else if(KeyValue == KEY2){
			OLED_Printf(90, 0, 6, "Key=2");
		}else if(KeyValue == KEY3){
			OLED_Printf(90, 0, 6, "Key=3");
		}
		vTaskDelay(pdMS_TO_TICKS(100));
	}
  /* USER CODE END AppTask_Oled_Display */
}
//ISR
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	if(hadc ->Instance == ADC1){
		ADC_Value = HAL_ADC_GetValue(hadc);
		BaseType_t highTaskWoken = pdFALSE;
		if(BinSem_AdcReadyHandle != NULL){
            //获取信号量,ADC采集完成给一个信号量
			xSemaphoreGiveFromISR(BinSem_AdcReadyHandle, &highTaskWoken);
			portYIELD_FROM_ISR(highTaskWoken);
		}
	}
}
/* USER CODE END Application */
2,计数信号量
void AppTask_Keys(void *argument)
{
  /* USER CODE BEGIN AppTask_Keys */
	OLED_Printf(0, 1, "Toral_tables=", uxSemaphoreGetCount(Sem_TablesHandle), 6);
	GPIO_PinState KeyState = GPIO_PIN_SET;
	/* Infinite loop */
	for (;;) {
		KeyState = HAL_GPIO_ReadPin(Key0_GPIO_Port, Key0_Pin);
		if(KeyState == GPIO_PIN_RESET){
            //桌子减少一个
			if(xSemaphoreTake(Sem_TablesHandle, pdMS_TO_TICKS(100)) == pdTRUE){
				OLED_ShowString(0, 3, "Check_In_OK", 6);
			}else{
				OLED_ShowString(0, 3, "Check_In_Fa", 6);
			}
			vTaskDelay(pdMS_TO_TICKS(300));
		}
		OLED_Printf(0, 2, "Avail_tables=", uxSemaphoreGetCount(Sem_TablesHandle),6);
		vTaskDelay(pdMS_TO_TICKS(10));
	}
  /* USER CODE END AppTask_Keys */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc){
	BaseType_t highTaskWoken = pdFALSE;
	if(Sem_TablesHandle != NULL){
		xSemaphoreGiveFromISR(Sem_TablesHandle, &highTaskWoken);//空桌子加一
		portYIELD_FROM_ISR(highTaskWoken);
	}
}3,互斥量
优先级反转



优先级继承











![模板[C++]](https://i-blog.csdnimg.cn/blog_migrate/da28dbc77d345a9061c0d2dbea14ecd7.gif)










