当前位置: 首页 > 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.xdnf.cn/news/1105813.html

相关文章:

  • P4597 序列 sequence题解
  • 跟着Carl学算法--二叉树【3】
  • 猿人学js逆向比赛第一届第十九题
  • 【每日算法】专题八_分治_归并排序
  • RLHF:人类反馈强化学习 | 对齐AI与人类价值观的核心引擎
  • Windows解决 ping 127.0.0.1 一般故障问题
  • 阿里云服务器,CentOS7.9上安装YApi 接口管理平台
  • Redis概念和基础
  • AI基建还能投多久?高盛:2-3年不是问题,回报窗口才刚开启
  • 学习C++、QT---21(QT中QFile库的QFile读取文件、写入文件的讲解)
  • MySQL内置函数(8)
  • Windows删除文件或者拔出U盘显示正在使用/占用解决办法
  • 必备软件推荐:1、Everything:Windows 文件查找的终极利器
  • CSS和CSS3区别对比
  • [面试] 手写题-插入排序
  • 网络安全第一次作业
  • 史上最详细Java并发多线程(面试必备,一篇足矣)
  • 视频翻译用什么软件?这里有5个高效推荐
  • 论迹不论心
  • 【天坑记录】cursor jsx文件保存时错误格式化了
  • 并发编程
  • C#元组:从基础到实战的全方位解析
  • 【C++类】
  • 速盾:高防CDN和普通CDN的区别大吗?
  • 【MySQL】———— 索引
  • 数据分析师如何构建自己的底层逻辑?
  • 12. 说一下 https 的加密过程
  • c++26新功能—copyable_function
  • 慕尚花坊项目笔记
  • MoE混合专家模型:千亿参数的高效推理引擎与架构革命