当前位置: 首页 > 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.dtcms.com/a/296662.html

相关文章:

  • 亚马逊Prime Day变革:精细化运营时代的号角
  • 基础05-Java控制流程:掌握if-else、switch和循环语句
  • 使用adb 发送广播 动态改变app内的值
  • 【PyTorch】图像二分类项目-部署
  • 【数字IC验证学习------- SOC 验证 和 IP验证和形式验证的区别】
  • NOTEPAD!NPCommand函数分析之comdlg32!GetSaveFileNameW--windows记事本源代码分析
  • 暑假集训篇之并发处理①练习题
  • prometheus监控k8s的metric详解-01-apiserver部分-05-其他
  • 局域网TCP通过组播放地址rtp推流和拉流实现实时喊话
  • 猎板碳油 PCB和普通PCB的区别
  • 【OpenCV实现多图像拼接】
  • kafka消费者组消费进度(Lag)深入理解
  • Redis--哨兵机制详解
  • Linux C:预处理命令
  • 225. 用队列实现栈
  • markdown学习笔记(个人向) Part.2
  • Redis高可用架构演进面试笔记
  • C#解析JSON数据全攻略
  • SpringBoot框架,不同环境中实体类对应不同的表
  • MySQL workbench的使用
  • Django 科普介绍:从入门到了解其核心魅力
  • 【Python】Python多线程爬虫实战:从基础原理到分布式架构实现
  • RCLAMP0512TQTCT 升特半导体 TVS二极管 12通道全防护芯片 以太网/PLC控制/5G基站专用
  • UE5中如何解决角色网格体“掉下去”的问题
  • 高并发系统设计面试题
  • 高效互联,ModbusTCP转EtherCAT网关赋能新能源电缆智能制造
  • Apache 消息队列分布式架构与原理
  • 六种经典智能优化算法(PSO/GWO/WOA/HHO/DBO/SSA)无人机(UAV)三维路径规划,Matlab代码实现
  • 【三桥君】大语言模型计算成本高,MoE如何有效降低成本?
  • Java学习---Spring及其衍生(下)