【STM32】FreeRTOS消息队列和信号量学习

一、消息队列(queue)

队列是一种用于实现任务与任务之间,任务与中断之间消息交流的机制。

注意:1.数据的操作是FIFO模式。

2.队列需要明确数据的大小和队列的长度。

3.写和读都会出现堵塞。

实验:创建一个消息队列,两个发送任务,一个接收任务。

其中任务一任务三的等待时间为0,任务二的等待时间为portMAX_DELAY(死等)。

实现:在前一个项目的基础上进行更改【STM32】利用CubeMX对FreeRTOS用按键控制任务

void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* Create the queue(s) *//* definition and creation of myQueue01 */osMessageQDef(myQueue01, 2, uint32_t);myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);/* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask02, osPriorityIdle, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* definition and creation of Task3 */osThreadDef(Task3, StartTask03, osPriorityIdle, 0, 128);Task3Handle = osThreadCreate(osThread(Task3), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */BaseType_t xStatus;uint32_t Buf=10086;for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){xStatus=xQueueSendToBack(myQueue01Handle,&Buf,0);if(xStatus!=pdTRUE){printf("NO1\r\n");osDelay(500);}else{printf("YES1%u\r\n",Buf);osDelay(500);}}}}/* USER CODE END StartDefaultTask */
}/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */BaseType_t xStatus;uint32_t Buf=66666;for(;;){		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){xStatus=xQueueSendToBack(myQueue01Handle,&Buf,portMAX_DELAY);if(xStatus!=pdTRUE){printf("NO2\r\n");osDelay(500);}else{printf("YES2%u\r\n",Buf);osDelay(500);}}}}/* USER CODE END StartTask02 */
}/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop *///BaseType_t xStatus;uint32_t Buf=0;for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){printf("当前%u\r\n",Buf);//xStatus=xQueueReceive(myQueue01Handle,&Buf,portMAX_DELAY);if(xQueueReceive(myQueue01Handle,&Buf,portMAX_DELAY)!=pdTRUE){printf("NO3\r\n");}else{printf("YES3%u\r\n",Buf);}}}}/* USER CODE END StartTask03 */
}

现象:队列满了以后,任务一无法发送,任务二会死等,队列空闲以后完成发送。

二、信号量

消息队列用于传输多个数据,占用时间也相对较长,但有时只需要传输状态,因此引入信号量。信号量也是队列的一种。信号量有两种,如果它的量只有0(被拿走的状态)和1(被填入的状态)两种状态,就称为二进制的信号量;当量的状态大于两种,就称为计数型信号量。

1.二值信号量

实验:任务一:按键采集数据;任务二:拿走以后串口发送信息

实现:

void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* definition and creation of myBinarySem01 */osSemaphoreDef(myBinarySem01);myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);/* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* Create the queue(s) *//* definition and creation of myQueue01 */osMessageQDef(myQueue01, 2, uint32_t);myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);/* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask02, osPriorityNormal, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* definition and creation of Task3 */osThreadDef(Task3, StartTask03, osPriorityNormal, 0, 128);Task3Handle = osThreadCreate(osThread(Task3), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */BaseType_t xStatus;uint32_t Buf=10086;for(;;){
//  {if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){
//				xStatus=xQueueSendToBack(myQueue01Handle,&Buf,0);if(xSemaphoreGive(myBinarySem01Handle)==pdTRUE){printf("NO1\r\n");}else{printf("YES1%u\r\n",Buf);}}}}/* USER CODE END StartDefaultTask */
}/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop */	uint32_t Buf=0;for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==0){				if(xSemaphoreTake(myBinarySem01Handle,0)==pdTRUE){printf("YES3\r\n");}else{printf("NO3%u\r\n",Buf);}}}}/* USER CODE END StartTask03 */
}

 现象:当按键释放了信号量,串口才能成功发送信息。

2.记数型信号量

实验:任务一 :按键一记录人进来;按键二记录人出去;(最多有10个人)

任务二:串口每隔3S打印人数。

实现:

void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* Create the semaphores(s) *//* definition and creation of myBinarySem01 */osSemaphoreDef(myBinarySem01);myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);/* definition and creation of myCountingSem01 */osSemaphoreDef(myCountingSem01);myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 10);/* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* Create the queue(s) *//* definition and creation of myQueue01 */osMessageQDef(myQueue01, 2, uint32_t);myQueue01Handle = osMessageCreate(osMessageQ(myQueue01), NULL);/* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartDefaultTask, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask02, osPriorityNormal, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* definition and creation of Task3 */osThreadDef(Task3, StartTask03, osPriorityNormal, 0, 128);Task3Handle = osThreadCreate(osThread(Task3), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0){if(xSemaphoreGive(myCountingSem01Handle)!=pdTRUE){printf("NO1\r\n");}else{printf("YES1\r\n");}}}if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){osDelay(20);if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0){if(xSemaphoreTake(myCountingSem01Handle,0)!=pdTRUE){printf("NO2\r\n");}else{printf("YES2\r\n");}}}}/* USER CODE END StartDefaultTask */
}/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */for(;;){}/* USER CODE END StartTask02 */
}/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the Task3 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop */for(;;){printf("possess %d people\r\n",(uint16_t)uxSemaphoreGetCount(myCountingSem01Handle));osDelay(3000);}/* USER CODE END StartTask03 */
}

 因为用了函数

myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 10);

默认当前计数值为满值。如果设置为0,使用下面的函数:

myCountingSem01Handle=xSemaphoreCreateCounting(10,0);

现象:通过按键一和二实现记录人数,并串口打印了当前人数。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA多线程和并发基础面试问答(翻译)

JAVA多线程和并发基础面试问答(翻译) java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序…

webpack中常见的Loader

目录 1.webpack中的loader是什么?配置方式 2. loader特性3.常见的loader 1.webpack中的loader是什么? loader 用于对模块的"源代码"进行转换,在 import 或"加载"模块时预处理文件 webpack做的事情,仅仅是分…

springboot 设置自定义启动banner背景图 教程

springboot banner Spring Boot中的banner是在应用程序启动时显示的一个ASCII艺术字符或文本。它被用来给用户展示一些关于应用程序的信息,例如名称、版本号或者公司标志等。 使用Spring Boot的默认设置,如果项目中有一个名为“banner.txt”的文件放置…

面试攻略,Java 基础面试 100 问(十一)

抽象类(abstract class)和接口(interface)有什么异同? 抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现&#xff…

Cpp学习——vector模拟实现

vector简介 在模拟实现vector之前,首先就得知道vector是个啥?vector是个啥呢?vector是一个stl里面的容器,并且是一个模板容器。它就像是一个顺序表模板。还记得顺序表吧?之前我实现的顺序表只能弄整形的数据&#xff0…

微信小程序 map地图(轨迹)

allMarkers效果图 废话少说直接上马(最后是我遇到的问题) cover-view是气泡弹窗,可以自定义弹窗,要配合js:customCallout,如果是非自定义的话:callout(可以修改颜色、边框宽度、圆角…

Ceph Reef版本 RBD 性能测试:80万写IOPS(10节点、60个NVMe SSD)

2023-05-16 08:30 发表于上海 摘自:https://mp.weixin.qq.com/s/mKkPElmCktoZaRk0m0IbqA 1、背景 Ceph 社区最近冻结了即将发布的 Ceph Reef 版本,今天我们研究一下 Ceph Reef 版本在 10 个节点、60 个 NVMe 磁盘的集群上的 RBD 性能。 在确保硬件没有…

医疗保健中的 NLP:实体链接

一、说明 HEalthcare和生命科学行业产生大量数据,这些数据是由合规性和监管要求,记录保存,研究论文等驱动的。但随着数据量的增加,搜索用于研究目的的必要文件和文章以及数据结构成为一个更加复杂和耗时的过程。例如,如…

小米平板6Max14即将发布:自研G1 电池管理芯片,支持33W反向快充

明天晚上7点(8 月 14 日),雷军将进行年度演讲,重点探讨“成长”主题。与此同时,小米将推出一系列全新产品,其中包括备受瞩目的小米MIX Fold 3折叠屏手机和小米平板6 Max 14。近期,小米官方一直在…

MiniPaint:在线图像编辑利器【在线PS】

MiniPaint在线图像编辑器使用 HTML5 实现图像的在线创建与编辑,在线PS,支持超过40种效果滤镜,无需本地安装,在很多应用场景中可以替代PhotopShop等传统软件。 访问地址:MiniPaint - 在线PS - 在线图像编辑。 1、打开图…

词法分析器的设计与实现

1、实验目的及要求 1.1、实验目的 加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。 1.2、实验要求 1)对单词…

Towards Open World Object Detection【论文解析】

Towards Open World Object Detection 摘要1 介绍2 相关研究3 开放世界目标检测4 ORE:开放世界目标检测器4.1 对比聚类4.2 RPN自动标注未知类别4.3 基于能量的未知标识4.4 减少遗忘 5 实验5.1开放世界评估协议5.2 实现细节5.3 开放世界目标检测结果5.4 增量目标检测结果 6 讨论…

Postman

Postman 简介下载安装 简介 Postman 是一款用于测试和开发 API(应用程序编程接口)的工具,它提供了用户友好的界面和丰富的功能,帮助开发者轻松地创建、测试、调试和文档化各种类型的 API。无论是在构建 Web 应用、移动应用还是其…

2023.08.13 学习周报

文章目录 摘要文献阅读1.题目2.要点3.问题4.解决方案5.本文贡献6.方法6.1 特征选择6.2 时间序列平稳性检测与数据分解6.3 基于GRU神经网络的PM2.5浓度预测 7.实验7.1 网络参数7.2 实验结果7.3 对比实验 8.讨论9.结论10.展望 PINNS模型1.自动微分2.全连接神经网络3.PINNs模型的P…

优雅地处理RabbitMQ中的消息丢失

目录 一、异常处理 二、消息重试机制 三、错误日志记录 四、死信队列 五、监控与告警 优雅地处理RabbitMQ中的消息丢失对于构建可靠的消息系统至关重要。下面将介绍一些优雅处理消息丢失的方案,包括异常处理、重试机制、错误日志记录、死信队列和监控告警等。…

Mac 卸载appium

安装了最新版的appium 2.0.1,使用中各种问题,卡顿....,最终决定回退的。记录下卸载的过程 1.打开终端应用程序 2.卸载全局安装的 Appium 运行以下命令以卸载全局安装的 Appium: npm uninstall -g appium 出现报错:Error: EACCES: permiss…

vue3项目中引入dialog插件,支持最大最小化、还原、拖拽

效果图: 上图是layui-vue组件库中的layer插件,我的项目使用的是element-plus组件库,在用不上layui组件库的情况下,就单独引入layui/layer-vue这个弹层插件就可以了 npm地址:layui/layer-vue - npm layui-vue组件库地址…

推荐几款流行的项目管理系统,助力高效团队协作!

项目式管理是目前非常流行的企业管理方法,这种方法让是如何在确保时间、技术、经费和性能指标的条件下,以尽可能高的效率完成预定目标,让所有与企业相关方满意。在这种模式下,团队的层次关系不再那么重要,大家以项目结…

【对于一维信号的匹配】对一个一维(时间)信号y使用自定义基B执行匹配追踪(MP)研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Android Https

本质:在客户端和服务端使用非对称加密协商出一套对称密钥,每次发送数据前加密,收到后解密,达到加密传输 http ssl 在http之下增加了安全层,用于保障http的加密传输 HTTPS连接 TLS连接步骤 1.客户端发送 client h…