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

FREERTOS根本不能使用连续接收串口思想

示例代码:

void middle_task(void *pvParameters) {while (1) {// 获取互斥锁访问共享资源
//        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {// 处理串口数据HandleSerialData(Serial1_GetRxFlag, Serial1_GetRxDatas, 1);HandleSerialData(Serial2_GetRxFlag, Serial2_GetRxDatas, 1);HandleSerialData(Serial3_GetRxFlag, Serial3_GetRxDatas, 1);HandleSerialData(Serial4_GetRxFlag, Serial4_GetRxDatas, 1);HandleSerialData(Serial5_GetRxFlag, Serial5_GetRxDatas, 1);//            xSemaphoreGive(xMutex);
//        }vTaskDelay(20);}
}
void HandleSerialData(uint8_t (*Serial_GetRxFlag)(void), uint8_t* (*Serial_GetRxDatas)(uint8_t),char explore) {if(Serial_GetRxFlag() == 1) { RxDatas = Serial_GetRxDatas(3); if(RxDatas[0] == 0x06 && RxDatas[1] == 0x01 && RxDatas[2] == 0x66) { Run_up();					 } if(RxDatas[0] == 0x06 && RxDatas[1] == 0x02 && RxDatas[2] == 0x66) { Run_down(); } if(RxDatas[0] == 0x06 && RxDatas[1] == 0x03 && RxDatas[2] == 0x66) { Run_left(); } if(RxDatas[0] == 0x06 && RxDatas[1] == 0x04 && RxDatas[2] == 0x66) { Run_right(); } if(RxDatas[0] == 0x06 && RxDatas[1] == 0x05 && RxDatas[2] == 0x66) { Run_forward(); } if(RxDatas[0] == 0x06 && RxDatas[1] == 0x06 && RxDatas[2] == 0x66) { Run_back(); }if(RxDatas[0] == 0x06 && RxDatas[1] == 0x07 && RxDatas[2] == 0x66) { Stepper_MoveSteps(10, 1, 5);}if(RxDatas[0] == 0x06 && RxDatas[1] == 0x08 && RxDatas[2] == 0x66) { Stepper_MoveSteps(10, 0, 5);
/* 获取多个数据 */
uint8_t* Serial1_GetRxDatas(int number)
{int timeout = 0;Serial1_RxDatas[0] = Serial1_GetRxData();for (int i = 1; i < number; i++){while (Serial1_GetRxFlag() == 0){if (++timeout > 2000) break;}Serial1_RxDatas[i] = Serial1_GetRxData();timeout = 0;}return Serial1_RxDatas;
}

这种连续接受思想在单线程芯片是可以用的,但在多线程或具有系统的单线程芯片中不行

在多线程环境中,这段代码存在严重的竞态条件(Race Condition)和线程安全问题。我来分析一下具体风险并提供改进方案。

问题分析

  1. 帧解析逻辑不完整

    • 只检查了3字节完整帧的情况(如 0x06 0x01 0x66

    • 没有处理帧不完整或数据错位的情况

    • 没有清除接收标志,可能导致重复处理相同数据

  2. 数据接收方式不合理

    • 使用 Serial_GetRxDatas(3) 假设每次都能获取完整帧

    • 实际串口数据可能被分包传输,需要状态机处理

  3. 全局变量冲突

    • RxDatas 是全局变量,被多个串口共享会导致数据覆盖

    • 缺少互斥锁保护共享数据

  4. 电机控制阻塞任务

    • Run_up() 等函数直接调用可能导致任务阻塞

    • 没有使用队列解耦接收和控制逻辑

这段代码在多线程环境中存在以下隐患:

  1. 共享资源竞争Serial1_RxDatas数组和接收标志Serial1_GetRxFlag()被多个线程访问,但没有同步机制
  2. 原子性问题Serial1_GetRxFlag()Serial1_GetRxData()的实现可能不是原子操作
  3. 数据一致性:读取过程中数据可能被其他线程修改
  4. 阻塞风险while循环可能导致整个系统阻塞

改进方案

以下是几种适用于 FreeRTOS 的改进方案:

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"// 定义互斥锁
SemaphoreHandle_t xSerialMutex;// 初始化函数
void Serial1_Init(void) {// 创建互斥锁xSerialMutex = xSemaphoreCreateMutex();
}uint8_t* Serial1_GetRxDatas(int number)
{int timeout = 0;// 获取互斥锁xSemaphoreTake(xSerialMutex, portMAX_DELAY);Serial1_RxDatas[0] = Serial1_GetRxData();for (int i = 1; i < number; i++){while (Serial1_GetRxFlag() == 0){if (++timeout > 2000) break;// 释放CPU时间片taskYIELD();}Serial1_RxDatas[i] = Serial1_GetRxData();timeout = 0;}// 释放互斥锁xSemaphoreGive(xSerialMutex);return Serial1_RxDatas;
}

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

相关文章:

  • C语言的程序控制语句
  • 多态 使用场景
  • 【构建Tomcat版本检查工具:自动检测并提醒版本更新】
  • 云、实时、时序数据库混合应用:医疗数据管理的革新与展望(中)
  • 解决Linux绑定失败地址已使用(端口被占用)的问题
  • day050-ansible剧本与变量
  • 云暴露面分析完整指南
  • 2025年7月11日—基础算法—高精度
  • 删除mysql文件夹时显示在另一程序中打开
  • 期权交易完整版教程简介
  • 工具分享--IP与域名提取工具
  • YOLOv13来了!基于超图增强的自适应视觉感知实时目标检测
  • 数据结构第一章复杂度的认识
  • WebSocket 重连与心跳机制:打造坚如磐石的实时连接
  • 005---Xilinx Viivado FIFO (二)---fifo IP核使用总结
  • python之set详谈
  • 大数据驱动的酒店用品需求预测模型研究 开发——毕业论文,毕业设计——仙盟创梦IDE
  • Linux驱动基本概念(内核态、用户态、模块、加载、卸载、设备注册、字符设备)
  • linux文件系统目录结构以及交互界面
  • 稳定币将成为新时代的重要金融工具
  • Pandas:数据类型转换
  • c99-柔性数组
  • NVME在ubuntu上总是导致死机
  • Android simpleperf生成火焰图
  • 深度解析 DApp 开发:从技术架构到商业落地的全链路解决
  • Linux 进程管理核心机制
  • 掌握Spring声明式事务传播机制:AOP与ThreadLocal的协同工作
  • 破解异构日志清洗五大难题,全面提升运维数据可观测性
  • 用FunctionCall实现文件解析(一):环境准备与基础知识
  • uniapp语音播报天气预报微信小程序