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

FreeRTOS队列实战:血氧监测系统设计

在 FreeRTOS 中,队列是实现任务间通信的核心机制,它提供了一种线程安全的数据传递方式。下面通过一个医疗器械中 ​血氧饱和度监测与报警​ ,来详细了解队列的使用方法。系统需要持续采集血氧数据,并在数据异常时触发报警。可以设计两个任务:一个数据采集任务和一个数据处理与报警任务,它们通过队列进行通信。

1. 定义数据结构与创建队列

首先,定义一个结构体来封装需要传输的数据,这使得单次通信可以传递多个相关变量,逻辑上更清晰。

#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"// 定义血氧数据结构体
typedef struct {uint8_t spo2;      // 血氧饱和度uint16_t heartRate; // 心率TickType_t timestamp; // 时间戳
} OxyData_t;// 队列参数
#define QUEUE_LENGTH 10 // 队列最多能容纳10条消息
#define QUEUE_ITEM_SIZE sizeof(OxyData_t) // 每条消息的大小为结构体的大小// 声明全局队列句柄
QueueHandle_t xOxyQueue;void app_main(void) {// 动态创建队列xOxyQueue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE);if (xOxyQueue == NULL) {// 队列创建失败,可能是内存不足,需要错误处理log("错误:队列创建失败!\n");return;}// 创建任务xTaskCreate(data_acquisition_task, "DataAcq", 2048, NULL, 2, NULL);//数据采集xTaskCreate(data_processing_task, "DataProc", 2048, NULL, 1, NULL); // 数据处理,优先级可低于或等于采集任务vTaskStartScheduler(); // 启动FreeRTOS调度器
}
2. 数据采集任务

这个任务模拟周期性地从传感器读取数据,并将数据发送到队列中。

void data_acquisition_task(void *pvParameters) {OxyData_t currentData = {0};const TickType_t xBlockTime = pdMS_TO_TICKS(1000); // 发送阻塞时间1秒for (;;) {// 模拟从传感器读取数据currentData.spo2 = simulate_spo2_read();currentData.heartRate = simulate_heart_rate_read();currentData.timestamp = xTaskGetTickCount(); // 获取当前系统时钟// 将数据发送到队列尾部// 如果队列满,任务将阻塞最多1秒(xBlockTime)BaseType_t xStatus = xQueueSend(xOxyQueue, &currentData, xBlockTime);if (xStatus != pdPASS) {// 发送失败,可能是队列在1秒内一直处于满的状态log("警告:数据包未能送入队列!\n");} else {log("数据已发送: SpO2=%d%%, HR=%d\n", currentData.spo2, currentData.heartRate);}vTaskDelay(pdMS_TO_TICKS(500)); // 每500ms采集一次}
}
3. 数据处理与报警任务

这个任务从队列中接收数据,进行检查并决定是否报警。

void data_processing_task(void *pvParameters) {OxyData_t receivedData;BaseType_t xStatus;for (;;) {// 从队列头部接收数据// 使用 portMAX_DELAY,表示如果队列为空则无限期阻塞,直到有数据到来xStatus = xQueueReceive(xOxyQueue, &receivedData, portMAX_DELAY);if (xStatus == pdPASS) {// 成功接收到数据,进行判断if (receivedData.spo2 < 90 || receivedData.heartRate < 50 || receivedData.heartRate > 160) {// 数据异常,触发报警trigger_alarm(receivedData.spo2, receivedData.heartRate);log("!!!报警!!! SpO2: %d%%, Heart Rate: %d\n", receivedData.spo2, receivedData.heartRate);} else {// 数据正常,记录或显示display_data(receivedData.spo2, receivedData.heartRate);log("数据正常: SpO2=%d%%, HR=%d\n", receivedData.spo2, receivedData.heartRate);}}// 由于使用了portMAX_DELAY,xStatus不是pdPASS的情况不会发生}
}

4.核心机制与注意事项

  1. 阻塞机制​:xQueueSendxQueueReceive的第三个参数 xTicksToWait实现了阻塞。这对系统稳定性至关重要,它能有效管理任务状态,避免任务空转消耗CPU资源。

    • 采集任务中设置1秒超时,防止在队列满时发送任务无限期阻塞,影响数据采集的周期性。

    • 处理任务中使用 portMAX_DELAY,确保没有数据时自动进入阻塞态,让出CPU,有数据时能立刻被唤醒。

  2. 线程安全​:队列操作本身是线程安全的。这意味着多个任务(或多个中断服务程序)同时访问同一个队列时,内部机制会保证数据不会损坏。

  3. 数据拷贝而非传递指针​:队列通过值传递​(拷贝数据本身),而不是传递指针。这确保了接收任务获得的是数据的一个完整副本,避免了发送任务在发送后修改数据而导致接收方数据错乱的风险。

  4. 中断服务程序中的使用​:如果数据采集是由硬件中断触发的,需要在中断服务程序中将数据发送到队列,此时必须使用中断专用函数 xQueueSendFromISR(),其内部进行了去除了阻塞等不适合在中断中执行的操作。

http://www.dtcms.com/a/542723.html

相关文章:

  • vscode使用verilog format插件教程
  • 锒川市住房和城乡建设局网站公告设计师培训基地
  • 在哪个网站做科目一考试题网站建设后如何修改
  • Linux Shell SSH命令
  • 哪个网站教做衣服深圳建设交易工程信息网
  • 无忧网站建设哪家好长沙整合推广
  • 沈阳好的网站网络营销工作岗位有哪些
  • 公司网站怎么写上海高端网站建设公
  • 南京网站设计是什么包装设计网站是什么样子的
  • 电子商务网站开发技术支持南京紫米网络科技有限公司
  • 响应式商业网站开发实训报告快速建站介绍
  • 2008iis网站属性网页设计报告2000字
  • QGraphicsEffect控件添加特效
  • 80s无水印视频素材网站下载无水印logo免费一键生成
  • 维护网站建设空间出租搜索引擎营销怎么做
  • 做版权保护的网站湖南网站建设制作
  • 广州门户网站建设wordpress改登录界面
  • 东莞市建设局网站公司网站建设注册
  • 网站备案怎么办网络空间安全考研
  • 通州网站建设是什么wordpress 4.7.2 被黑
  • 新乐网站制作价格商标注册名字查询系统
  • 网站建设专业介绍佛山应用软件开发
  • 宁波网站推广在哪里一个网站多个域名的seo优化
  • 长春seo公司网站制作网站优化
  • 【win11】funasr 2:安装了两套miniconda环境咋办
  • 购买源码的网站建设通破解vip
  • 佛山营销网站建设制作快速生成网站
  • 滨海网站建设网站子网页设计
  • 网站开发属于无形资产大一网页设计代码英语
  • 设计素材网站推荐pin优化大师怎么卸载