计数型信号量

news2024/12/23 18:15:58

回顾上节所讲:

Q: 什么是信号量?

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

计数型信号量相当于队列长度大于1 的队列,因此计数型信号量能够容纳多个资源,计数型信号量的值反应的是资源的状态

关于计数信号量的理解,比较经典的就是“停车场”,假如停车场有3个车位,那么这就是个计数值为3的计数信号量,每当有一辆车开进停车场,计数值就会减1,如果停车场停满了3辆车,计数值就会为0,此时有新的车开过停车场,只需要查看计数值就知道,无法进入停车,只能返回或者继续等着。

 

 计数型信号量相关 API 函数

  • uxMaxCount:可以达到的最大计数值
  • uxInitialCount:创建信号量时分配给信号量的计数值
  • 返回值: 成功,返回对应计数型信号量的句柄; 失败,返回 NULL 

 除了创建有略微的区别,计数型信号量的释放和获取与二值信号量完全相同 !

实操演示

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

由于计数信号量和二值信号量的实现非常类似,所以直接复制上节二值信号量的Cube文件“mjm_freeRTOS_Sema_Bi” 并重命名为 “mjm_freeRTOS_Sema_coun

 打开相应的Cube文件: 

1. 配置按钮的GPIO:

2.  找到左侧的Middleware --> FREERTOS:

2.1 在“Config parameters”,将“USE_COUNTING_SEMAPHORES” 设置为 “Enabled”:

2.2 在“Timers and Semaphores”,删除刚刚创建的二值信号量,并创建一个新的计数信号量:

 

 

3. 生成代码打开Keil:

3.1 查看生成计数信号量的函数:

跳转这个函数并查看计数型信号量的部分:

 

可见,Cube封装的这个函数在创建计数型信号量的时候,将“xSemaphoreCreateCounting()" 的两个输入参数都设置为了count,所以和二值信号量一样,在创建计数信号量的时候,会同时释放所有的信号量。

3.2 代码实现:

#include "stdio.h"

void StartTaskGive(void const * argument)
{
  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){ //按键消抖
				printf("KEY1 has been pressed\r\n");
				if (xSemaphoreGive(myCountingSemHandle) == pdTRUE){ //释放信号量并判断返回值,如果返回成功
					printf("successfully give\r\n");
				}else{//如果返回失败
					printf("fail to give\r\n");
				}		
			}
			while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); //等待按键松开,防止出现按钮一直按着,就一直删除创建任务			
		}
		osDelay(10);
  }
}


void StartTaskTake(void const * argument)
{
  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){ //按键消抖
				printf("KEY2 has been pressed\r\n");
				if (xSemaphoreTake(myCountingSemHandle, 0 ) == pdTRUE){ //获取信号量并判断返回值,如果返回成功 
					printf("successfully take\r\n");
				}else{//如果返回失败
					printf("fail to take\r\n");
				}
			}
			while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET); //等待按键松开,防止出现按钮一直按着,就一直删除创建任务			
		}
		osDelay(10);
  }
}

可见,关于计数信号量的获取和释放,其实除了函数不同之外其余完全相同!

实现效果

打开串口助手,先按一下KEY1:

如上面所说,创建计数信号量的函数将“uxInitialCount” 设为了3,所以一旦创建就先全部被释放了,所以再次释放不成功。

那么此时连按四下KEY2:

每获取一次,计数量减1,三次之后计数信号量被全部获取,计数值归0,所以在第四次获取失败

此时再按四下KEY1:

每释放一次,计数值加1,三次之后计数信号量全部被释放,计数值为3,所以在第四次释放失败

 

 

 

 

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

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

相关文章

本地Git仓库和GitHub仓库SSH传输

SSH创建命令解释 ssh-keygen 用于创建密钥的程序 -m PEM 将密钥的格式设为 PEM -t rsa 要创建的密钥类型,本例中为 RSA 格式 -b 4096 密钥的位数,本例中为 4096 -C “azureusermyserver” 追加到公钥文件末尾以便于识别的注释。 通常以电子邮件地址…

【Android常见问题(五)】- Flutter项目性能优化

文章目录 知识回顾前言源码分析1. 渲染过程2. 分析工具3. 优化方法合理使用const关键词合理使用组件管理着色器编译垃圾 知识回顾 前言 项目迭代开发一定程度后,性能优化是重中之重,其中包括了包体积,UI 渲染、交互等多个方面。 通过 Flutt…

ssm停车场信息管理系统java车辆车位收费jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当做编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 ssm停车场信息管理系统 系统有2权限:管理…

浏览器端代理proxy 解决跨域

一.环境:使用expresshttp-proxy-middleware 直接上代码 // include dependencies const express require( express);//node内置的path模块导入 const path require("path")const { createProxyMiddleware } require( http-proxy-middleware); // 需要代理后端服…

Linux6.12 Docker 数据管理和镜像的创建

文章目录 计算机系统5G云计算第四章 LINUX Docker 数据管理和镜像的创建一、Docker 的数据管理1.数据卷2.数据卷容器 二、容器互联(使用centos镜像)三、Docker 镜像的创建1.基于现有镜像创建1)首先启动一个镜像,在容器里做修改2&a…

通达信指标回测系统的高级玩法:优化参数

#1.本期主要的学习内容: A.找到最优的选股信号,即最佳参数的寻找方法。 B.学会使用通达信内置的(程序交易评测系统)指标回测系统。 #2.程序交易评测系统的打开方法 选择公式——程序交易评测系统 快捷键:CTRLS 键…

了解Unity编辑器之组件篇Event(七)

Event:用于在对象之间进行通信和交互的机制。它可以帮助你实现触发和响应特定动作或状态的逻辑一、Event System:用于处理 UI 事件的系统组件 First Selected 属性:定义了在场景加载或 UI 激活时,哪个 UI 元素将成为首选的选中元素…

动态内存管理学习分享

动态内存管理学习分享 1. 为什么存在动态内存分配2. 动态内存函数的介绍2.1 [malloc](https://legacy.cplusplus.com/reference/cstdlib/malloc/?kwmalloc)和[free](https://legacy.cplusplus.com/reference/cstdlib/free/?kwfree)2.1.1 实例 2.2 [calloc](https://legacy.cp…

TikTok标签观看量破347亿次!芭比妆容蕴藏巨大商机!

据外媒报道,随着真人版电影《芭比》的上映,英国在线市场上与芭比美容产品的搜索量急剧上升。芭比娃娃成为许多人共有的童年记忆,也成为了独树一帜的文化标志。 TikTok标签观看量破347亿次!芭比妆容蕴藏巨大商机! 英国…

麒麟信安携手兆芯、信创桥发布信创联合解决方案,合力推动行业信创加速落地

近年来,加快构建自主创新基础软硬件生态已成为保障我国信息安全的重要一环,优先选择基于自主安全技术路线的国产芯片、操作系统等基础软硬件及关键业务应用软件已成为行业共识。但由于当前wintel体系下的部分复杂应用暂时难以迁移至自主平台,…

Java BIO、NIO、AIO

操作系统中的 I/O 以上是 Java 对操作系统的各种 IO 模型的封装,【文件的输入、输出】在文件处理时,其实依赖操作系统层面的 IO 操作实现的。【把磁盘的数据读到内存种】操作系统中的 IO 有 5 种: 阻塞、 非阻塞、【轮询】 异步、 IO复…

Linux-Shell

1.什么是Bash shell(壳) Bash Shell是一个命令解释器,它在操作系统的最外层,负责用户程序与内核进行交互操作的一种接口,将用户输入的命令翻译给操作系统,并将处理后的结果输出至屏幕。 通过xshell连接,就是打开了一…

精益生产管理工具有哪些?3大必备的精益管理软件!

​企业往往需要管理成千上万的数据,并保证整个管理过程的效率和质量,因此企业往往需要用到一些高效的管理软件,以应对管理过程中的各种问题。今天针对这个问题,与大家分享3大必备的精益管理软件,相信你在工作中一定能用…

为什么新版内核将进程pid管理从bitmap替换成了radix-tree?

第一次写进程创建的时候我使用的内核版本还是 3.10 的版本。在这个版本里已分配的进程 pid 号是用 bitmap 来存储的。但在 5.4 和 6.1 版本里,发现进程 pid 号管理实现已经从 bitmap 替换成了基数树(radix-tree)。后来翻了下版本更新历史&…

springboot项目新增子module

1. 拉取项目 2. file-new-module 3. 选择版本 4. 1-2-3-4 5. 注释请求统一前缀 (SwaggerConfig.java)

CSDN增加挂饰

就是添加一些代码即可&#xff1a; 添加代码&#xff1a; <div> <p> </p><span style"color:#A67D3D;">个人网站&#xff1a;</span> <img src"https://dezeming.top/wp-content/uploads/2022/07/Dezeming-261x300.png"…

UE使用UnLua(二)

1.前言 最近也是比较忙&#xff0c;忘了来更新了&#xff0c;好多都是开了头断更的&#xff08;狗头&#xff09;&#xff0c;今天抽空再更一篇&#xff01;&#xff01; 这篇讲一下在UnLua中覆盖蓝图事件&#xff08;函数&#xff09;&#xff0c;及按钮、文本控件的一些使用…

多线程———生产者和消费者(等待唤醒机制)彻底理解以及代码实现

目录 一、何为等待唤醒机制(生产者消费者模式)&#xff1f; 如何实现等待唤醒机制&#xff1f; 二、等待唤醒机制(生产者消费者模式)代码实现&#xff1a; 1、生产者代码&#xff1a; 2.桌子代码&#xff08;控制生产者和消费者&#xff09;&#xff1a; 3.消费者代码&am…

Simulink仿真模块 - Bus Selector

us Selector:从传入总线中选择元素 在仿真库中的位置为:Simulink / Commonly Used Blocks Simulink / Signal Routing HDL Coder / Signal Routing 模型为: 说明 Bus Selector 模块输出您从输入总线选择的元素。该模块可以单独输出所选的各元素或在一个新的虚拟总线中输出所…

浅谈智能电容器在低压配电网末端的应用

安科瑞 华楠 摘要&#xff1a;电容器优化配置和投切是配电网络优化的一项重要内容。电容器优化配置&#xff0c;侧重对电容器优化投切的各种算法进行了详细评述&#xff0c;分析了各种算法的特点及存在的问题&#xff0c;以促进该研究领域的进一步发展。 关键词&#xff1a;电…