FreeRTOS信号量使用详解
目录概述1 信号量概述2 FreeRTOS信号量类型2.1 二进制信号量Binary Semaphore2.2 计数信号量Counting Semaphore2.3 互斥信号量Mutex2.4 递归互斥量Recursive Mutex3 信号量API函数详解3.1 创建信号量3.2 获取/释放信号量3.3 中断服务程序中的信号量操作3.4 其他函数4 使用示例4.1 二进制信号量示例任务同步4.2 计数信号量示例资源池管理4.3 互斥量示例保护共享资源4.4 递归互斥量示例4.5 ISR中使用信号量概述FreeRTOS中信号量是用于任务间同步和资源管理的重要机制。信号量分为二进制信号量、计数型信号量和互斥信号量互斥锁。下面将详细说明它们的使用方法。1 信号量概述信号量是FreeRTOS中用于任务间同步和互斥的重要机制主要用于任务同步通知某个事件发生资源管理控制对共享资源的访问任务通信在任务间传递状态信息信号量选择原则场景推荐信号量类型任务同步二进制信号量资源计数计数信号量保护共享资源互斥量任务可能多次获取同一锁递归互斥量2 FreeRTOS信号量类型2.1 二进制信号量Binary Semaphore只有0和1两种状态常用于任务同步2.2 计数信号量Counting Semaphore计数器值可以从0到最大值用于管理多个相同的资源2.3 互斥信号量Mutex特殊的二进制信号量具有优先级继承机制防止优先级反转2.4 递归互斥量Recursive Mutex允许同一任务多次获取锁必须释放相同次数才能完全解锁3 信号量API函数详解3.1 创建信号量/* 创建二进制信号量 */ SemaphoreHandle_t xSemaphoreCreateBinary(void); /* 创建计数信号量 */ SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, /* 最大计数值 */ UBaseType_t uxInitialCount /* 初始计数值 */ ); /* 创建互斥量 */ SemaphoreHandle_t xSemaphoreCreateMutex(void); /* 创建递归互斥量 */ SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);3.2 获取/释放信号量/* 获取信号量阻塞 */ BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, /* 信号量句柄 */ TickType_t xTicksToWait /* 超时时间 */ ); /* 获取信号量非阻塞 */ xSemaphoreTake(xSemaphore, 0); /* 获取信号量无限等待 */ xSemaphoreTake(xSemaphore, portMAX_DELAY); /* 释放信号量 */ BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore); /* 获取递归互斥量 */ BaseType_t xSemaphoreTakeRecursive( SemaphoreHandle_t xMutex, TickType_t xTicksToWait ); /* 释放递归互斥量 */ BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex);3.3 中断服务程序中的信号量操作/* 在ISR中释放信号量 */ BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken ); /* 在ISR中获取信号量 */ BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );3.4 其他函数/* 删除信号量 */ void vSemaphoreDelete(SemaphoreHandle_t xSemaphore); /* 获取信号量计数值 */ UBaseType_t uxSemaphoreGetCount(SemaphoreHandle_t xSemaphore);4 使用示例4.1 二进制信号量示例任务同步#include FreeRTOS.h #include task.h #include semphr.h /* 定义信号量句柄 */ SemaphoreHandle_t xBinarySemaphore; /* 任务1等待事件 */ void vTask1(void *pvParameters) { for(;;) { /* 等待信号量 */ if(xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) pdTRUE) { /* 收到信号量执行相应操作 */ printf(Task1: Event received!\n); } vTaskDelay(100 / portTICK_PERIOD_MS); } } /* 任务2触发事件 */ void vTask2(void *pvParameters) { for(;;) { /* 每隔1秒触发一次事件 */ vTaskDelay(1000 / portTICK_PERIOD_MS); /* 释放信号量 */ xSemaphoreGive(xBinarySemaphore); printf(Task2: Event triggered!\n); } } /* 主函数 */ int main(void) { /* 创建二进制信号量初始值为0 */ xBinarySemaphore xSemaphoreCreateBinary(); if(xBinarySemaphore ! NULL) { /* 创建任务 */ xTaskCreate(vTask1, Task1, configMINIMAL_STACK_SIZE, NULL, 1, NULL); xTaskCreate(vTask2, Task2, configMINIMAL_STACK_SIZE, NULL, 2, NULL); /* 启动调度器 */ vTaskStartScheduler(); } /* 如果调度器启动失败会执行到这里 */ for(;;); }4.2 计数信号量示例资源池管理/* 模拟有3个可用资源 */ #define MAX_RESOURCES 3 SemaphoreHandle_t xCountingSemaphore; /* 资源使用者任务 */ void vResourceUserTask(void *pvParameters) { char *pcTaskName (char *)pvParameters; for(;;) { /* 请求资源 */ printf(%s: Requesting resource...\n, pcTaskName); if(xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) pdTRUE) { /* 获取到资源使用一段时间 */ printf(%s: Got resource, using...\n, pcTaskName); vTaskDelay(500 / portTICK_PERIOD_MS); /* 释放资源 */ xSemaphoreGive(xCountingSemaphore); printf(%s: Released resource\n, pcTaskName); } vTaskDelay(1000 / portTICK_PERIOD_MS); } } int main(void) { /* 创建计数信号量初始有3个资源可用 */ xCountingSemaphore xSemaphoreCreateCounting(MAX_RESOURCES, MAX_RESOURCES); if(xCountingSemaphore ! NULL) { /* 创建多个资源使用者任务 */ xTaskCreate(vResourceUserTask, User1, configMINIMAL_STACK_SIZE, User1, 1, NULL); xTaskCreate(vResourceUserTask, User2, configMINIMAL_STACK_SIZE, User2, 1, NULL); xTaskCreate(vResourceUserTask, User3, configMINIMAL_STACK_SIZE, User3, 1, NULL); xTaskCreate(vResourceUserTask, User4, configMINIMAL_STACK_SIZE, User4, 1, NULL); vTaskStartScheduler(); } for(;;); }4.3 互斥量示例保护共享资源#include stdio.h /* 共享资源 */ int iSharedVariable 0; SemaphoreHandle_t xMutex; /* 任务访问共享资源 */ void vAccessSharedResource(void *pvParameters) { char *pcTaskName (char *)pvParameters; int iLocalCopy; for(;;) { /* 获取互斥锁 */ if(xSemaphoreTake(xMutex, portMAX_DELAY) pdTRUE) { /* 临界区开始 */ iLocalCopy iSharedVariable; printf(%s: Read value %d\n, pcTaskName, iLocalCopy); vTaskDelay(50 / portTICK_PERIOD_MS); /* 模拟处理时间 */ iLocalCopy; iSharedVariable iLocalCopy; printf(%s: Updated value %d\n, pcTaskName, iSharedVariable); /* 临界区结束 */ /* 释放互斥锁 */ xSemaphoreGive(xMutex); } vTaskDelay(100 / portTICK_PERIOD_MS); } } int main(void) { /* 创建互斥量 */ xMutex xSemaphoreCreateMutex(); if(xMutex ! NULL) { /* 创建两个任务同时访问共享资源 */ xTaskCreate(vAccessSharedResource, TaskA, configMINIMAL_STACK_SIZE, TaskA, 2, NULL); xTaskCreate(vAccessSharedResource, TaskB, configMINIMAL_STACK_SIZE, TaskB, 1, NULL); vTaskStartScheduler(); } for(;;); }4.4 递归互斥量示例SemaphoreHandle_t xRecursiveMutex; void vRecursiveFunction(int depth) { char buffer[50]; /* 获取递归锁 */ if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) pdTRUE) { sprintf(buffer, Depth %d: Got lock, depth); printf(%s\n, buffer); if(depth 3) { /* 递归调用 */ vRecursiveFunction(depth 1); } /* 释放递归锁 */ xSemaphoreGiveRecursive(xRecursiveMutex); sprintf(buffer, Depth %d: Released lock, depth); printf(%s\n, buffer); } } void vRecursiveTask(void *pvParameters) { for(;;) { vRecursiveFunction(1); vTaskDelay(1000 / portTICK_PERIOD_MS); } } int main(void) { xRecursiveMutex xSemaphoreCreateRecursiveMutex(); if(xRecursiveMutex ! NULL) { xTaskCreate(vRecursiveTask, RecTask, configMINIMAL_STACK_SIZE, NULL, 1, NULL); vTaskStartScheduler(); } for(;;); }4.5 ISR中使用信号量/* 定义信号量句柄 */ SemaphoreHandle_t xSemaphoreFromISR; /* 中断服务程序 */ void vExampleInterruptHandler(void) { BaseType_t xHigherPriorityTaskWoken pdFALSE; /* 在ISR中释放信号量 */ xSemaphoreGiveFromISR(xSemaphoreFromISR, xHigherPriorityTaskWoken); /* 如果需要任务切换 */ portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } /* 任务处理中断事件 */ void vISRHandlerTask(void *pvParameters) { for(;;) { /* 等待来自ISR的信号量 */ if(xSemaphoreTake(xSemaphoreFromISR, portMAX_DELAY) pdTRUE) { /* 处理中断事件 */ printf(ISR event handled in task\n); } } } int main(void) { /* 创建二进制信号量 */ xSemaphoreFromISR xSemaphoreCreateBinary(); if(xSemaphoreFromISR ! NULL) { /* 配置中断 */ // configure_interrupt(); /* 创建处理任务 */ xTaskCreate(vISRHandlerTask, ISRHandler, configMINIMAL_STACK_SIZE, NULL, 3, NULL); vTaskStartScheduler(); } for(;;); }

相关新闻

Java毕设项目:基于springboot的城市人才招聘系统的设计与实现(源码+文档,讲解、调试运行,定制等)

Java毕设项目:基于springboot的城市人才招聘系统的设计与实现(源码+文档,讲解、调试运行,定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/5/17 4:03:27 阅读更多 →
【课程设计/毕业设计】基于springboot的面向新工科课程线上教学辅助平台教辅资源系统的设计与实现【附源码、数据库、万字文档】

【课程设计/毕业设计】基于springboot的面向新工科课程线上教学辅助平台教辅资源系统的设计与实现【附源码、数据库、万字文档】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/3 21:12:27 阅读更多 →
输入手机各应用使用时长,分类统计娱乐/工作/学习占比,并给出健康建议。

输入手机各应用使用时长,分类统计娱乐/工作/学习占比,并给出健康建议。

1️⃣ 实际应用场景描述 & 痛点引入在数字化生活中,人们每天使用手机的时间很长,但往往不清楚时间都花在了哪里。尤其是学生、上班族,可能娱乐时间过长,影响工作与学习。痛点:- 无法量化各类应用的使用占比。- 容易…

2026/7/3 3:22:59 阅读更多 →

最新新闻

嵌入式系统多电压轨供电方案设计与优化

嵌入式系统多电压轨供电方案设计与优化

1. 为什么需要三重降压转换方案在嵌入式系统和工业控制领域,多电压轨供电已经成为标准需求。现代电子设备通常需要3.3V给主控芯片供电、1.8V供给DDR内存、5V驱动外围接口,传统的单路降压方案需要多个独立电源模块,不仅占用PCB面积&#xff0c…

2026/7/3 22:09:56 阅读更多 →
IDM永久激活终极指南:3分钟免费解锁下载神器完整教程

IDM永久激活终极指南:3分钟免费解锁下载神器完整教程

IDM永久激活终极指南:3分钟免费解锁下载神器完整教程 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script 还在为Internet Download Manager(I…

2026/7/3 22:09:55 阅读更多 →
文件上传漏洞深度解析:从SPON系统漏洞复现到安全防御实践

文件上传漏洞深度解析:从SPON系统漏洞复现到安全防御实践

1. 项目概述最近在梳理一些网络设备的安全风险时,一个名为“世邦通信SPON IP网络对讲广播系统”的设备引起了我的注意。这套系统在不少园区、学校、工厂里都能见到,主要用来做背景音乐、紧急广播和对讲。它基于IP网络传输音频,听起来挺现代化…

2026/7/3 22:09:55 阅读更多 →
工业自动化中的多通道ADC系统设计与优化

工业自动化中的多通道ADC系统设计与优化

1. 项目背景与核心器件选型在工业自动化与精密测量领域,多通道信号采集与控制系统是各类监测设备的核心模块。TPAFE0808作为一款8通道12位模数转换器(ADC),配合PIC18F4685微控制器构建的解决方案,能够实现对温度、压力、流量等多种工业信号的…

2026/7/3 22:07:55 阅读更多 →
【计算机Java毕业设计案例】基于 SpringBoot 的商超会员折扣与收银结算系统的设计与实现 商场限时折扣满减优惠管理系统(程序+文档+讲解+定制)

【计算机Java毕业设计案例】基于 SpringBoot 的商超会员折扣与收银结算系统的设计与实现 商场限时折扣满减优惠管理系统(程序+文档+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/3 22:05:55 阅读更多 →
告别“聊完就忘”的 AI:程序员必看的 AI Agent Harness 与 Hermes 深度解析

告别“聊完就忘”的 AI:程序员必看的 AI Agent Harness 与 Hermes 深度解析

引言 作为一名身处 2026 年的程序员,你一定经历过这种令人抓狂的“赛博西西弗斯”时刻: 你打开了一个 AI 编程助手(无论是网页端的对话框,还是 IDE 里的插件),耐心地把项目的目录结构、团队的命名规范、甚…

2026/7/3 22:05:55 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻