当前位置: 首页 > news >正文

FreeRTOS篇8:二值信号量

一.什么是信号量?

信号量(Semaphore),是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代 码段不被并发调用。

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

信号量也是队列的一种。

二.什么是二值信号量?

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

互斥访问:比如门钥匙,只有获取到钥匙才可以开门

任务同步:比如我录完视频你才可以看视频

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

1. 创建二值信号量

 

参数:

返回值:

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

2. 释放二值信号量

参数:

xSemaphore:要释放的信号量句柄

返回值:

成功,返回 pdPASS ; 失败,返回 errQUEUE_FULL 。

3. 获取二值信号量

 

参数:

xSemaphore:要获取的信号量句柄

xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;

返回值:

成功,返回 pdPASS ;

失败,返回 errQUEUE_FULL 。

四.实操

1.实验需求

创建一个二值信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

2.cubeMX配置

创建任务

创建二值信号量

3.代码实现

 

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId taskGiveHandle;
osThreadId taskTakeHandle;
osSemaphoreId myBinarySemHandle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartTaskGive(void const * argument);
void StartTaskTake(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* definition and creation of myBinarySem */osSemaphoreDef(myBinarySem);myBinarySemHandle = osSemaphoreCreate(osSemaphore(myBinarySem), 1);/* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of taskGive */osThreadDef(taskGive, StartTaskGive, osPriorityNormal, 0, 128);taskGiveHandle = osThreadCreate(osThread(taskGive), NULL);/* definition and creation of taskTake */osThreadDef(taskTake, StartTaskTake, osPriorityNormal, 0, 128);taskTakeHandle = osThreadCreate(osThread(taskTake), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartTaskGive */
/*** @brief  Function implementing the taskGive thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartTaskGive */
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");elseprintf("二值信号量放入失败\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");elseprintf("二值信号量放入失败\r\n");}while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskTake */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */


http://www.mrgr.cn/news/41760.html

相关文章:

  • Stream流的终结方法
  • 使用python iter方法读取文件
  • arduino点亮墨水屏
  • 第十四讲-输入控件QPlainTextEdit
  • “衣依”服装销售平台:Spring Boot技术实践与创新
  • 深度学习应用
  • YOLO11改进|上采样篇|引入DySample轻量级动态上采样器
  • 昇思MindSpore进阶教程--在ResNet-50网络上应用二阶优化实践(上)
  • 计算机网络期末复习真题(附真题答案)
  • 奶茶在线小程序介绍
  • Linux运维必知应知命令集合
  • 物联网智能项目探究和方案设计
  • ChatGPT效率指南!轻松掌握提高生产力的秘诀!
  • 06 Docker容器内部管理的终极指南:掌握核心技巧与最佳实践
  • 图形化部署Java Web项目的3款工具大全
  • SQL Server—T-sql使用Select查询详解
  • 基于SSM的校园快递一站式服务系统【附源码】
  • 在一个克隆的仓库中设置远程仓库并同步最新的更改
  • 【Linux私房菜(九)之进程间通信】
  • 性能测试为什么需要收集度量指标