STM32信号量

news2024/11/27 21:43:13

目录

什么是信号量?

什么是二值信号量?

二值信号量相关 API 函数

1. 创建二值信号量

2. 释放二值信号量

3. 获取二值信号量

实操

实验需求

cubeMX配置​编辑

代码实现

计数型信号量

什么是计数型信号量?

计数型信号量相关 API 函数

实操

实验需求

cubeMX配置

代码实现 


什么是信号量?

信号量( Semaphore ),是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代
码段不被并发调用。
信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用,然后我们的量还可以
用来表示资源的数量,当我们的量只有 0 1 的时候,它就可以被称作二值信号量,只有两个状
态,当我们的那个量没有限制的时候,它就可以被称作为计数型信号量。
信号量也是队列的一种

什么是二值信号量?

 

二值信号量其实就是一个长度为 1 ,大小为零的队列,只有 0 1 两种状态,通常情况下,我们用
它来进行互斥访问或任务同步。
互斥访问:比如门钥匙,只有获取到钥匙才可以开门
任务同步:比如我录完视频你才可以看视频

二值信号量相关 API 函数

函数
描述
xSemaphoreCreateBinary()
使用动态方式创建二值信号量
xSemaphoreCreateBinaryStatic()
使用静态方式创建二值信号量
xSemaphoreGive()
释放信号量
xSemaphoreGiveFromISR()
在中断中释放信号量
xSemaphoreTake()
获取信号量
xSemaphoreTakeFromISR()
在中断中获取信号量

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

实操

实验需求

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

cubeMX配置

代码实现

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);
	myBinarySemHandle = xSemaphoreCreateBinary();
  /* 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");
				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 */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

计数型信号量

什么是计数型信号量?

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

计数型信号量相关 API 函数

函数
描述
xSemaphoreCreateCounting()
使用动态方法创建计数型信号量。
xSemaphoreCreateCountingStatic()
使用静态方法创建计数型信号量
uxSemaphoreGetCount()
获取信号量的计数值
计数型信号量的释放和获取与二值信号量完全相同 !
SemaphoreHandle_t xSemaphoreCreateCounting ( UBaseType_t uxMaxCount ,
UBaseType_t uxInitialCount );
参数:
uxMaxCount :可以达到的最大计数值 uxInitialCount :创建信号量时分配给信号量的计数值
返回值:
成功,返回对应计数型信号量的句柄;
失败,返回 NULL

实操

实验需求

创建一个计数型信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

cubeMX配置

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

 

代码实现 

 

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 myCountingSem */
  osSemaphoreDef(myCountingSem);
//  myCountingSemHandle = osSemaphoreCreate(osSemaphore(myCountingSem), 3);
	myCountingSemHandle = xSemaphoreCreateCounting(3, 0);
  /* 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(myCountingSemHandle) == 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(myCountingSemHandle, 0 ) == 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 */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/628906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CENTO OS上的网络安全工具(二十三)VSCODE SPARK 容器式编程环境构建

在vscode上使用maven构建spark的scala编程环境,很大程度上需要不断地从网络上下载各种依赖和插件,而且这一过程复杂而不可控。下面这段,是整个安装过程中/root目录下不断增加的内容。 [rootd7ff8f448a0d /]# cd /root [rootd7ff8f448a0d ~]#…

【 Python 全栈开发 - WEB开发篇 - 32 】MySQL高级查询

文章目录 一、LIMIT限制查询结果的数量二、使用GROUP BY进行分组查询1.GROUP BY和聚合函数一起使用2.GROUP BY和聚合函数以及HAVING一起使用 三、使用ORDER BY对查询结果排序 一、LIMIT限制查询结果的数量 开始之前,我们先准备一下数据,打开cmd&#xf…

MsSqlServer2008R2移动数据库迁移复制粘贴附加.mdf不要.ldf日志 230609记录

MsSqlServer2008R2数据库迁移复制粘贴附加.mdf 230609记录 将一个SqlServer的某个数据文件.mdf拷贝到另一个数据库当中,并启用 操作工具为 SSMS(SQL Server Management Studio) 19.1 免费下载 SQL Server Management Studio (SSMS) 19.1 .mdf文件 SQL Server 数据库中的三…

【数据结构】何为数据结构。

🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星T…

chatgpt赋能python:Python循环暂停和继续的方法

Python循环暂停和继续的方法 Python是一种高级编程语言,在编程中使用循环结构非常常见。很多情况下,我们需要在循环中暂停或者继续执行。在本文中,我们将介绍如何在Python中实现循环暂停和继续的方法。 循环暂停和继续的意义 在Python编程…

打死也要学的VUE.js(中文官方文档)

VUE.js中文官方文档 文章目录 VUE.js中文官方文档 创建一个 Vue 应用[#](https://cn.vuejs.org/guide/essentials/application.html#creating-a-vue-application)应用实例[#](https://cn.vuejs.org/guide/essentials/application.html#the-application-instance)根组件[#](http…

微信小程序抓包你会吗?不会我来教你

目录 前言 先来说小程序抓包问题 再说下小程序调试问题 解包wxapkg 调试小程序 总结: 前言 今天聊下微信小程序的抓取,其实小程序的抓取不难,主要解决抓包和如何调试小程序这两个问题。如果你运用chrome调试已经比较熟练了的话,就…

Java多线程、进程、并行、并发的理解(通俗易懂)

程序(programm) 概念:是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码。 进程(process) 概念:程序的一次执行过程,或是正在运行的一个程序。 说明:进程作为资源分配的单位,系统在运行时会为每…

基于VITS-fast-fine-tuning构建多speaker语音训练

1 VITS模型介绍 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)是一种语音合成方法,它使用预先训练好的语音编码器 (vocoder声码器) 将文本转化为语音。 VITS 的工作流程如下: &#xff0…

【CSS按钮特效】css如何实现科技感好看按钮效果(尾附源码下载)

【写在前面】这两天还是比较痴迷于CSS特效的,甚至还想着去用CSS做动画片呢,希望后面能做到,今天主要讲的是我们页面常见的元素-按钮,很多时候按钮也需要高级化,但是很多人苦于没有途径去寻找,于是乎借这个机…

jsx底层渲染机制,函数组件的底层渲染机制

jsx底层渲染机制!! 1.第一大步创建virtualDom 首先把我们编写的JSX语法,编译为虚拟DOM对象「virtualDOM」,这一步也分为两小步 虚拟DON对象∶框架自己内部构建的一套对象体系(对象的相关成员都是React内部规定的)&a…

深入理解深度学习——注意力机制(Attention Mechanism):多头注意力(Multihead Attention)

分类目录:《深入理解深度学习》总目录 在实践中,当给定相同的查询、键和值的集合时,我们希望模型可以基于相同的注意力机制学习到不同的行为, 然后将不同的行为作为知识组合起来, 捕获序列内各种范围的依赖关系 &#…

论文解读:GBPNet:蛋白质结构的通用几何表示学习

GBPNet: Universal Geometric Representation Learning on Protein Structures DOI:https://doi.org/10.1145/3534678.3539441 Github:GBPNet/gbpnet/datamodules at main sarpaykent/GBPNet GitHub 摘要: 蛋白质3D结构的表示学习对于例如计算蛋白质设计或蛋白…

单链表OJ题:LeetCode--160.相交链表

朋友们、伙计们,我们又见面了,本期来给大家解读一下LeetCode中第160道单链表OJ题,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! 数据结构与算法专栏:数据结构与算法 个 人…

Lecture 19 Question Answering

目录 introductionIR-based QA (dominant approach)Knowledge-based QAHybrid QAConclusion introduction Definition: question answering (“QA”) is the task of automatically determining the answer for a natural language questionMostly focus on “factoid” quest…

牛客网论坛最具争议的Linux内核成神笔记,GitHub已下载量已过百万

原文地址:牛客网论坛最具争议的Linux内核成神笔记,GitHub已下载量已过百万 1、前言 Linux内核是一个操作系统(OS)内核,本质上定义为类Unix。它用于不同的操作系统,主要是以不同的Linux发行版的形式。Linu…

网红如何创建百度百科词条?

随着互联网的发展,越来越多的人开始从事网红行业。对于网红来说,提升自己的个人形象至关重要,一个提升品牌形象的快速方式就是创建百度百科词条。网红如何创建百度百科词条?如何创建一个高质量的百度百科词条?下面伯乐…

万维网服务器

一、域名解析gethostbyname函数 struct hostent {char *h_name; /* 官方域名 */char **h_aliases; /* 别名*/int h_addrtype; /* 地址族(地址类型) */int h_length; /* 地址长度 */char **h_addr_list; …

Qt扫盲-Qt事件系统概述

Qt事件系统概述 一、概述二、事件类型 - Event Types三、事件处理程序 - Event Handlers四、事件过滤器 - Event Filters五、发送事件 - Sending Events1. sendEvent()2. postEvent() 一、概述 在Qt中,事件是由抽象的QEvent类派生而来的对象,表示发生在…

凌恩全新育种分析流程!助力种质资源高分文章发表!

种质资源又称遗传资源。种质是指生物体亲代传递给子代的遗传物质,它往往存在于特定品种之中。如古老的地方品种、新培育的推广品种、重要的遗传材料,野生近缘植物以及利用上述繁殖材料创造的各种遗传材料,都属于种质资源的范围,是…