一,信号量
有时候任务之间传递的只是一个标致,让进程之间同步,会对一个共享资源的互斥性访问,这时候就可以用信号量和互斥量。
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);
}
}