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

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.lryc.cn/news/598761.html

相关文章:

  • Unity UI的未来之路:从UGUI到UI Toolkit的架构演进与特性剖析(3)
  • 【自动化运维神器Ansible】Ansible常用模块之shell模块详解
  • 深入解析Hadoop NameNode的Full GC问题、堆外内存泄漏及元数据分治策略
  • Lua(数组)
  • DBA常用数据库查询语句(2)
  • 详解FreeRTOS开发过程(六)-- 队列
  • Redis操作
  • PostgreSQL 跨库查询方法
  • CMake ARGV变量使用指南
  • 基于C语言的Zynq SOC FPGA嵌入式裸机设计和开发教程
  • 外企本土化布局对国内连接器企业影响几何?
  • 模型的存储、加载和部署
  • rust-切片类型
  • centos7中把nginx更新到1.26 版(centos7默认只能更新到1.20)
  • IROS-2025 | OIKG:基于观察-图交互与关键细节引导的视觉语言导航
  • 【LeetCode 热题 100】39. 组合总和——(解法一)选或不选
  • windwos11网页切换残留/卡屏/冻结/残影问题
  • Java学习---Spring及其衍生(下)
  • 基于SpringBoot+Vue的电脑维修管理系统(WebSocket实时聊天、Echarts图形化分析)
  • 类和包的可见性
  • 磁性材料如何破解服务器电源高频损耗难题?
  • Linux C 网络基础编程
  • Redis高可用架构演进面试笔记
  • 13-C语言:第13天笔记
  • mysql索引底层B+树
  • HTTP/1.0、HTTP/1.1 和 HTTP/2.0 主要区别
  • OpenLayers 综合案例-基础图层控制
  • 主要分布在背侧海马体(dHPC)CA1区域(dCA1)的位置细胞对NLP中的深层语义分析的积极影响和启示
  • 《Java语言程序设计》第2章复习题(3)
  • 高亮标题里的某个关键字正则表达式