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

FreeRTOS—计数型信号量

文章目录

  • 一、计数型信号量简介
  • 二、计数型信号量相关API函数
    • 2.1.动态方法创建计数型信号量
    • 2.2.获取信号量的计数值
  • 三、实验
    • 3.1.实验设计
    • 3.2.软件设计

一、计数型信号量简介

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

  • 事件计数:当每次事件发生后,在事件处理函数中释放计数型信号量(计数值+1),其他任务会获取计数型信号量(计数值-1),这种场合一般在创建时将初始计数值设置为 0
  • 资源管理:信号量表示有效的资源数目,任务必须先获取信号量(信号量计数值-1)才能获取资源控制权,当计数值减为零时表示没有的资源。当任务使用完资源后,必须释放信号量(信号量计数值+1),信号量创建时计数值应等于最大资源数目

二、计数型信号量相关API函数

使用计数型信号量的过程:创建计数型信号量 - 释放信号量 - 获取信号量,该方法与使用二值信号量一致:

函数描述
xSemaphoreCreateCounting( )使用动态方法创建计数型信号量
uxSemaphoreGetCount( )获取信号量的计数值

2.1.动态方法创建计数型信号量

此函数用于使用动态方式创建计数型信号量,创建计数型信号量所需的内存,由 FreeRTOS 从 FreeRTOS 管理的堆中进行分配。该函数实际上是一个宏定义,在 semphr.h 中有定义,具体的代码如下所示:

#define xSemaphoreCreateCounting(uxMaxCount, uxInitialCount)      xQueueCreateCountingSemaphore((uxMaxCount),       (uxInitialCount)) 

下面表格是它的形参和描述:

形参描述
uxMaxCount计数值的最大值限定
uxInitialCount计数值的初始值

下面表格是它的返回值:

返回值描述
NULL创建失败
其他值创建成功返回计数型信号量的句柄

2.2.获取信号量的计数值

此函数用于获取信号量当前计数值的大小:

#define uxSemaphoreGetCount(xSemaphore)uxQueueMessagesWaiting((QueueHandle_t)(xSemaphore))

下面表格是它的形参和描述:

形参描述
xSemaphore信号量的句柄

下面表格是它的返回值:

返回值描述
整数当前信号量的计数值大小

三、实验

3.1.实验设计

本实验将设计三个任务:

  • start_task:用来创建 task1 和 task2 任务
  • task1:用于按键扫描,当检测到按键 KEY0 被按下时,释放计数型信号量
  • task2:每过一秒获取一次计数型信号量,当成功获取后打印信号量计数值

3.2.软件设计

和二值信号量创建一样,再入口函数里面创建,定义了最大释放数值为 10,从 0 开始计数:

QueueHandle_t count_semphr_handle;	//定义这个计数型信号量的句柄
void freertos_demo(void)
{count_semphr_handle = xSemaphoreCreateCounting(10,0);if(count_semphr_handle != NULL){printf("计数型信号量创建成功\r\n");}xTaskCreate((TaskFunction_t)    start_task,(char*)             "start_task",(uint16_t)          START_TASK_STACK_SIZE,(void*)             NULL,(UBaseType_t)       START_TASK_PRIO,(TaskHandle_t*)     &start_task_handler);vTaskStartScheduler();  		
}

下面是 task1 的代码,按下按键,就释放一次信号量,最多只能释放到 10:

void task1(void *pvParameters)
{uint8_t key = 0;BaseType_t err = 0;while(1){key = key_scan(0);if(key == KEY0_PRES){err = xSemaphoreGive(count_semphr_handle);if(err == pdPASS){printf("信号量释放成功\r\n");}}}
}

下面是 task2 的代码,每个 2s 就消耗一次资源,当资源为 0 时,task2 进入阻塞态,需要 task1 按键按下才有资源运行:

void task2(void *pvParameters)
{while(1){xSemaphoreTake(count_semphr_handle, portMAX_DELAY);printf("还剩%d资源\r\n",uxSemaphoreGetCount(count_semphr_handle));vTaskDelay(2000);}
}

下图是运行结果,为什么一开始按下按键就显示还剩 0 资源,因为按下按键之后,代码顺序是先消耗,再打印结果出来:
在这里插入图片描述

http://www.xdnf.cn/news/16180.html

相关文章:

  • Django基础(八)———数据库外键及表关系
  • Cisco 主模式配置
  • iOS Core Data 本地数据库 使用详解:从模型关系到数据操作
  • Python(09)正则表达式
  • HTTP性能优化实战:从协议到工具的全面加速指南
  • 大语言模型中提示词技术的原理、演进与未来发展研究
  • 基于Qt和OpenCV的图片与视频编辑器
  • 从0到1学习c++ 命名空间
  • Hive常用函数
  • GitHub Actions打包容器,推送 AWS ECR 并使 EKS 自动拉取以完成发版部署
  • [ComfyUI] --ComfyUI 是什么?比 Stable Diffusion WebUI 强在哪?
  • Linux Wlan 无线网络驱动开发-scan协议全流程详解
  • QT开发---字符编码与QString和QByteArray
  • 深度分析Java内存回收机制
  • 基于深度学习的图像分类:使用EfficientNet实现高效分类
  • RocketMQ搭建及测试(Windows环境)
  • 大模型处理私有数据的核心技术
  • 【News】同为科技亮相首届气象经济博览会
  • Django Models详解:数据库模型的核心
  • 第二十七章 W55MH32 Interrupt示例
  • go语言基础教程:【1】基础语法:变量
  • 爬虫基础概念
  • 数学基础弱能学好大数据技术吗?
  • Kubernetes 集群架构和Pod创建流程
  • tcp基础协议
  • 字节的机器人模型 GR-3
  • 高可用架构模式——如何应对接口级的故障
  • uni-app支付宝小程序样式穿透失效
  • C51:用DS18B20传感器读取温度
  • 如何将拥有的域名自定义链接到我的世界服务器(Minecraft服务器)