STM32提高串口发送函数执行速度并避免丢帧方法

目录

  • 前言
  • 一、使用非阻塞模式(中断或DMA)
  • a、使用中断驱动的传输
  • b. 使用 DMA 驱动的传输
  • 二、 增大缓冲区和优化数据管理
  • a. 增大发送缓冲区
  • b. 优化数据传输逻辑
  • 三、 提高 UART 的配置效率
  • a. 增加 UART 的波特率
  • b. 调整 UART 配置参数
  • 四、 优化缓冲区和内存管理
  • a. 使用环形缓冲区
  • b. 减少数据复制
  • 五、使用更高效的传输函数
  • a. 直接操作寄存器
  • b. 使用轻量级库或自定义驱动
  • 六、优化中断和任务优先级
  • a. 提高 UART 中断优先级
  • b. 合理安排任务优先级(RTOS 环境)
  • 七、实现双缓冲技术
  • 八、 其他优化建议
  • a. 避免使用阻塞函数
  • b. 优化系统时钟配置
  • c. 使用双核或多核微控制器
  • 九、示例代码:使用 DMA 和环形缓冲区优化 UART 传输
  • a. 定义缓冲区和管理变量
  • b. 实现缓冲区管理函数
  • c. 主函数和初始化
  • 总结

  • 前言

    提高串口发送函数的执行速度并尽量避免丢帧,涉及优化数据传输的方法、减少阻塞时间以及合理管理缓冲区。以下是几种有效的方法和详细的实现步骤:


    一、使用非阻塞模式(中断或DMA)

    a、使用中断驱动的传输

    原理:利用 UART 中断驱动数据发送,避免在传输过程中阻塞主线程。每当 UART 发送一个字节完成时,触发中断并发送下一个字节。
    实现步骤:
    1.初始化 UART 并启用发送中断:

    // 假设使用的是 STM32 HAL 库
    HAL_UART_Transmit_IT(&huart1, buffer, length);
    

    2.实现中断回调函数:

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            // 发送完成后的处理
            // 可以开始下一个传输或设置标志位
        }
    }
    
    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            // 错误处理
        }
    }
    

    3.管理传输队列:
    使用一个环形缓冲区(环形队列)来存储待发送的数据。主线程将数据放入队列,中断处理函数从队列中取出数据并发送。

    #define TX_BUFFER_SIZE 256
    uint8_t txBuffer[TX_BUFFER_SIZE];
    volatile uint16_t txHead = 0;
    volatile uint16_t txTail = 0;
    
    void enqueueTxData(uint8_t data) {
        uint16_t nextHead = (txHead + 1) % TX_BUFFER_SIZE;
        if (nextHead != txTail) { // 检查缓冲区是否满
            txBuffer[txHead] = data;
            txHead = nextHead;
        }
        // 处理缓冲区满的情况
    }
    
    uint8_t dequeueTxData(void) {
        uint8_t data = 0;
        if (txTail != txHead) { // 检查缓冲区是否为空
            data = txBuffer[txTail];
            txTail = (txTail + 1) % TX_BUFFER_SIZE;
        }
        return data;
    }
    
    void startNextTransmission(UART_HandleTypeDef *huart) {
        if (txTail != txHead) {
            uint8_t data = dequeueTxData();
            HAL_UART_Transmit_IT(huart, &data, 1);
        }
    }
    
    // 在 HAL_UART_TxCpltCallback 中调用
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            startNextTransmission(huart);
        }
    }
    
    // 主线程发送数据
    void sendData(uint8_t *data, uint16_t length) {
        for (uint16_t i = 0; i < length; i++) {
            enqueueTxData(data[i]);
        }
        // 如果没有正在发送,启动传输
        if (txTail == txHead) {
            startNextTransmission(&huart1);
        }
    }
    
    

    b. 使用 DMA 驱动的传输

    原理:利用 DMA(Direct Memory Access)控制器进行数据传输,减少 CPU 负担,提高传输效率。DMA 可以在后台自动将数据从内存复制到 UART 数据寄存器,无需 CPU 介入。

    实现步骤:
    1.初始化 UART 并配置 DMA:

    // 在 CubeMX 中配置 USART1 使用 DMA 进行 TX 传输
    // 生成初始化代码
    

    2.使用 HAL_UART_Transmit_DMA:

    HAL_UART_Transmit_DMA(&huart1, buffer, length);
    

    3.实现 DMA 传输完成回调:

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            // DMA 传输完成后的处理
            // 可以开始下一个传输或设置标志位
        }
    }
    
    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            // 错误处理
        }
    }
    

    4.管理传输队列:
    类似于中断驱动的方法,使用环形缓冲区存储待发送数据。当 DMA 传输完成后,从队列中取出下一个数据块并启动新的 DMA 传输。

    #define TX_BUFFER_SIZE 1024
    uint8_t txBuffer[TX_BUFFER_SIZE];
    volatile uint16_t txHead = 0;
    volatile uint16_t txTail = 0;
    
    void enqueueTxData(uint8_t *data, uint16_t length) {
        for (uint16_t i = 0; i < length; i++) {
            uint16_t nextHead = (txHead + 1) % TX_BUFFER_SIZE;
            if (nextHead != txTail) { // 检查缓冲区是否满
                txBuffer[txHead] = data[i];
                txHead = nextHead;
            } else {
                // 处理缓冲区满的情况,例如丢弃数据或等待
            }
        }
    }
    
    void startNextDMA(UART_HandleTypeDef *huart) {
        if (txTail != txHead) {
            uint16_t remaining = (txHead >= txTail) ? (txHead - txTail) : (TX_BUFFER_SIZE - txTail);
            HAL_UART_Transmit_DMA(huart, &txBuffer[txTail], remaining);
            txTail = (txTail + remaining) % TX_BUFFER_SIZE;
        }
    }
    
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            startNextDMA(huart);
        }
    }
    
    void sendData(uint8_t *data, uint16_t length) {
        enqueueTxData(data, length);
        // 如果没有正在发送,启动传输
        if (txTail == txHead) {
            startNextDMA(&huart1);
        }
    }
    

    优点:
    提高传输效率:DMA 可以在后台传输数据,无需 CPU 介入,释放 CPU 资源处理其他任务。
    减少中断负担:DMA 传输完成后只触发一次中断,而中断驱动模式每发送一个字节都会触发中断。

    注意事项:
    缓冲区管理:确保缓冲区足够大,避免溢出。
    错误处理:处理 DMA 传输错误,例如缓冲区溢出或传输失败。

    二、 增大缓冲区和优化数据管理

    a. 增大发送缓冲区

    原理:增加发送缓冲区的大小,减少频繁启动传输的次数,提高整体传输效率。

    实现步骤:
    在环形缓冲区或 DMA 缓冲区中使用较大的数据块进行传输,减少中断或 DMA 传输启动的频率。

    #define TX_BUFFER_SIZE 2048 // 根据需求调整
    uint8_t txBuffer[TX_BUFFER_SIZE];
    volatile uint16_t txHead = 0;
    volatile uint16_t txTail = 0;
    

    优点
    减少传输启动次数:一次传输大量数据,减少中断或 DMA 启动的频率。
    提高传输效率:一次传输多个字节,提高数据吞吐量。

    注意事项
    内存占用:确保系统有足够的内存来支持较大的缓冲区。
    实时性:在实时性要求较高的应用中,可能需要平衡缓冲区大小与实时响应能力。

    b. 优化数据传输逻辑

    原理:减少不必要的数据复制和传输次数,优化数据管理逻辑,提高传输效率。

    实现步骤

    避免频繁调用传输函数:批量传输数据,减少函数调用次数。
    使用指针操作:直接操作数据指针,减少数据复制。

    // 例如,批量传输多个数据块
    void sendDataBatch(uint8_t *data, uint16_t length) {
        while (length > 0) {
            uint16_t chunk = (length > MAX_CHUNK_SIZE) ? MAX_CHUNK_SIZE : length;
            enqueueTxData(data, chunk);
            data += chunk;
            length -= chunk;
        }
        // 启动传输
        if (txTail == txHead) {
            startNextTransmission(&huart1);
        }
    }
    

    三、 提高 UART 的配置效率

    a. 增加 UART 的波特率

    原理:增加 UART 的波特率可以提高数据传输速率,减少传输时间。

    实现步骤

    调整波特率配置
    在 CubeMX 中配置 UART 的波特率,例如从 115200 增加到 921600。

    确保硬件支持高波特率
    确保你的硬件(微控制器和接收端设备)支持更高的波特率,并且信号完整性良好。

    优点
    提高传输速率:更高的波特率意味着更快的数据传输。
    减少传输时间:同样数量的数据在更短的时间内传输完成。

    注意事项
    信号完整性:高波特率可能导致信号干扰和误码率增加,确保 PCB 设计良好,必要时使用屏蔽和差分信号。
    硬件限制:某些 UART 硬件模块对波特率有上限,需查阅具体微控制器的参考手册。

    b. 调整 UART 配置参数

    原理:优化 UART 的配置参数(如数据位、停止位、奇偶校验)以提高传输效率。

    实现步骤

    数据位:使用 8 数据位是常见配置,兼容性最好。
    停止位:使用 1 个停止位而不是 2 个,可以稍微提高传输速率。
    奇偶校验:如果不需要错误检测,可以禁用奇偶校验,以减少传输时间。

    示例

    huart1.Init.BaudRate = 921600; // 提高波特率
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    HAL_UART_Init(&huart1);
    

    优点
    提高传输效率:减少每个数据包的占用时间。
    减少协议开销:禁用奇偶校验减少额外的数据位。

    注意事项
    兼容性:确保接收端设备支持相同的配置参数。
    错误率:禁用奇偶校验可能增加数据错误的风险,需权衡传输效率和数据完整性。

    四、 优化缓冲区和内存管理

    a. 使用环形缓冲区

    原理:使用环形缓冲区(环形队列)来管理发送和接收数据,减少数据复制和提高传输效率。

    实现步骤

    定义环形缓冲区

    #define RX_BUFFER_SIZE 512
    uint8_t rxBuffer[RX_BUFFER_SIZE];
    volatile uint16_t rxHead = 0;
    volatile uint16_t rxTail = 0;
    
    #define TX_BUFFER_SIZE 512
    uint8_t txBuffer[TX_BUFFER_SIZE];
    volatile uint16_t txHead = 0;
    volatile uint16_t txTail = 0;
    

    实现缓冲区管理函数

    // Enqueue data
    void enqueueTxData(uint8_t data) {
        uint16_t nextHead = (txHead + 1) % TX_BUFFER_SIZE;
        if (nextHead != txTail) { // 检查缓冲区是否满
            txBuffer[txHead] = data;
            txHead = nextHead;
        }
        // 处理缓冲区满的情况
    }
    
    // Dequeue data
    uint8_t dequeueTxData(void) {
        uint8_t data = 0;
        if (txTail != txHead) { // 检查缓冲区是否为空
            data = txBuffer[txTail];
            txTail = (txTail + 1) % TX_BUFFER_SIZE;
        }
        return data;
    }
    

    优点
    高效管理数据:环形缓冲区能够高效地管理连续的数据流。
    减少内存碎片:避免动态内存分配导致的碎片问题。

    注意事项
    缓冲区大小:根据应用需求选择合适的缓冲区大小,避免溢出。
    线程安全:在多线程环境下,确保缓冲区访问的线程安全,可以使用互斥锁或禁用中断。

    b. 减少数据复制

    原理:尽量减少数据在传输过程中的复制,直接使用指针或引用传输数据,提升效率。

    实现步骤

    直接传输数据块:避免逐字节传输,使用批量数据传输。

    void sendData(uint8_t *data, uint16_t length) {
        // 确保数据长度不超过缓冲区容量
        for (uint16_t i = 0; i < length; i++) {
            enqueueTxData(data[i]);
        }
        // 启动传输
        if (txTail == txHead) {
            startNextTransmission(&huart1);
        }
    }
    使用指针管理缓冲区:
    
    c
    复制代码
    // 使用指针进行数据传输
    void sendData(uint8_t *data, uint16_t length) {
        while (length > 0) {
            uint16_t space = TX_BUFFER_SIZE - txHead;
            uint16_t chunk = (length < space) ? length : space;
            memcpy(&txBuffer[txHead], data, chunk);
            txHead = (txHead + chunk) % TX_BUFFER_SIZE;
            data += chunk;
            length -= chunk;
        }
        // 启动传输
        if (txTail == txHead - chunk) {
            startNextTransmission(&huart1);
        }
    }
    

    优点
    提高传输效率:减少数据复制步骤,提高传输速度。
    简化代码逻辑:通过指针管理,简化数据传输逻辑。

    注意事项
    内存管理:确保数据指针有效,避免悬空指针或越界访问。
    数据对齐:确保数据块对齐,避免传输过程中出现对齐错误。

    五、使用更高效的传输函数

    a. 直接操作寄存器

    原理:直接操作 UART 数据寄存器,绕过 HAL 库的封装,减少函数调用开销,提升传输速度。

    实现步骤

    实现非阻塞传输函数

    void UART_SendByte(UART_HandleTypeDef *huart, uint8_t byte) {
        // 等待发送寄存器为空
        while (!(huart->Instance->SR & USART_SR_TXE));
        huart->Instance->DR = byte;
    }
    
    void UART_SendData(UART_HandleTypeDef *huart, uint8_t *data, uint16_t length) {
        for (uint16_t i = 0; i < length; i++) {
            UART_SendByte(huart, data[i]);
        }
        // 等待传输完成
        while (!(huart->Instance->SR & USART_SR_TC));
    }
    

    使用 DMA 或中断优化
    结合 DMA 或中断驱动的数据发送,进一步提升效率。

    优点
    减少开销:直接操作寄存器,避免 HAL 函数的额外开销。
    提升速度:更快速的传输响应。

    注意事项
    可维护性:直接操作寄存器可能降低代码的可读性和可维护性。
    错误处理:需要手动实现错误检测和处理机制。

    b. 使用轻量级库或自定义驱动

    原理:使用更轻量级的 UART 驱动库,减少不必要的功能和开销,提升传输速度。

    实现步骤
    选择轻量级驱动:例如 ChibiOS 或其他开源实时操作系统,提供更高效的 UART 驱动。
    自定义优化:根据项目需求自定义优化 UART 驱动,去除不必要的功能,提升传输效率。

    优点
    灵活性:可以根据具体需求进行定制和优化。
    性能提升:去除不必要的功能,提高驱动效率。

    注意事项
    开发时间:需要花费更多时间进行驱动开发和测试。
    兼容性:确保自定义驱动与现有系统和硬件兼容。

    六、优化中断和任务优先级

    a. 提高 UART 中断优先级

    原理:提高 UART 中断的优先级,确保数据传输的及时处理,减少中断延迟。

    实现步骤

    配置中断优先级

    // 使用 NVIC 设置 USART1 中断优先级
    HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
    

    确保中断处理及时
    确保中断处理函数简洁高效,避免长时间占用 CPU 资源。

    优点
    及时处理数据:高优先级中断可以更快地响应数据传输请求。
    减少丢帧风险:及时处理中断,减少数据丢失的可能性。

    注意事项
    优先级冲突:避免将 UART 中断优先级设置得过高,导致其他关键任务被阻塞。
    中断嵌套:小心处理中断嵌套,避免优先级反转和死锁。

    b. 合理安排任务优先级(RTOS 环境)

    原理:在使用实时操作系统(如 FreeRTOS)的情况下,合理安排任务优先级,确保 UART 传输任务具有足够的优先级。

    实现步骤

    定义任务优先级

    #define UART_TASK_PRIORITY (osPriorityAboveNormal)
    

    创建 UART 传输任务

    void UART_Task(void *argument) {
        while (1) {
            // 处理发送队列
            sendDataFromQueue();
            osDelay(1); // 适当的延迟
        }
    }
    
    // 在主函数中创建任务
    osThreadDef(UART_Thread, UART_Task, UART_TASK_PRIORITY, 0, 128);
    osThreadCreate(osThread(UART_Thread), NULL);
    

    优点
    提高任务响应:高优先级任务能够更快地响应数据传输需求。
    减少任务延迟:合理安排任务优先级,确保关键任务不会被低优先级任务阻塞。

    注意事项
    优先级分配:确保高优先级任务不会导致低优先级任务长时间被阻塞。
    资源管理:避免优先级反转和资源争用,确保任务调度的公平性。

    七、实现双缓冲技术

    原理
    双缓冲技术使用两个缓冲区交替进行数据传输,一个缓冲区用于数据准备,另一个缓冲区用于传输,减少等待时间和提高传输效率。

    实现步骤
    定义双缓冲区

    #define BUFFER_SIZE 512
    uint8_t buffer1[BUFFER_SIZE];
    uint8_t buffer2[BUFFER_SIZE];
    volatile uint8_t currentBuffer = 0;
    

    实现缓冲区切换

    void switchBuffer(void) {
        if (currentBuffer == 0) {
            HAL_UART_Transmit_DMA(&huart1, buffer1, BUFFER_SIZE);
            currentBuffer = 1;
        } else {
            HAL_UART_Transmit_DMA(&huart1, buffer2, BUFFER_SIZE);
            currentBuffer = 0;
        }
    }
    
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            switchBuffer();
        }
    }
    
    void prepareBuffer(uint8_t *data, uint16_t length) {
        if (currentBuffer == 0) {
            memcpy(buffer2, data, length); // 准备下一个缓冲区
        } else {
            memcpy(buffer1, data, length);
        }
        // 传输已经在中断回调中处理
    }
    

    优点
    减少传输等待时间:一个缓冲区传输时,另一个缓冲区可以准备数据,减少传输等待。
    提高吞吐量:双缓冲技术能够更高效地利用 DMA 传输,提高整体数据吞吐量。

    注意事项
    同步管理:确保缓冲区切换和数据准备的同步,避免数据覆盖或丢失。
    内存占用:双缓冲技术需要额外的内存来存储两个缓冲区。

    八、 其他优化建议

    a. 避免使用阻塞函数

    原理:阻塞函数会阻塞当前线程,导致 CPU 无法处理其他任务,影响整体系统性能。

    实现步骤

    使用非阻塞传输:使用中断或 DMA 驱动的传输方式,避免阻塞函数的使用。
    优化主循环:确保主循环或任务能够高效执行,避免长时间占用 CPU。

    优点
    提高系统响应性:非阻塞传输允许系统同时处理多个任务,提高响应速度。
    减少丢帧风险:避免因阻塞导致的数据传输延迟或丢帧。

    注意事项
    复杂性:非阻塞传输可能增加代码复杂性,需要合理管理状态和回调。

    b. 优化系统时钟配置

    原理:提高系统时钟频率可以提升整个系统的运行速度,包括 UART 传输。

    实现步骤

    调整系统时钟配置
    在 CubeMX 中配置更高的系统时钟频率(例如,从 72 MHz 提高到 168 MHz)。

    确保硬件支持
    确保微控制器的时钟配置稳定,电源设计满足更高频率下的需求。

    优点
    提高系统性能:更高的系统时钟频率提升 CPU 和外设的运行速度。
    加快数据处理:更高的 CPU 频率可以更快地处理数据传输和其他任务。

    注意事项
    功耗增加:更高的系统时钟频率会增加功耗,需要权衡性能和功耗。
    散热管理:高频率运行可能导致温度升高,确保良好的散热设计。

    c. 使用双核或多核微控制器

    原理:利用多核微控制器将数据传输任务和其他任务分离,提高整体系统性能和传输效率。

    实现步骤

    选择多核微控制器
    选择支持双核或多核架构的微控制器,如 ARM Cortex-M7 与 Cortex-M4 的组合。

    任务分离
    将数据传输任务分配到一个核心,其他任务分配到另一个核心,减少任务间的干扰和延迟。

    优点
    并行处理:提高系统的并行处理能力,提升传输效率和系统响应速度。
    任务隔离:减少任务间的干扰,提高系统的可靠性和稳定性。

    注意事项
    复杂性增加:多核系统需要更复杂的任务管理和同步机制。
    成本和功耗:多核系统通常成本更高,功耗也更大。

    九、示例代码:使用 DMA 和环形缓冲区优化 UART 传输

    以下是一个综合示例,展示如何结合 DMA 驱动和环形缓冲区来优化 UART 传输,提升传输速度并减少丢帧。

    a. 定义缓冲区和管理变量

    #define TX_BUFFER_SIZE 1024
    uint8_t txBuffer[TX_BUFFER_SIZE];
    volatile uint16_t txHead = 0;
    volatile uint16_t txTail = 0;
    volatile uint8_t txInProgress = 0;
    

    b. 实现缓冲区管理函数

    // Enqueue data into the transmit buffer
    void enqueueTxData(uint8_t *data, uint16_t length) {
        for (uint16_t i = 0; i < length; i++) {
            uint16_t nextHead = (txHead + 1) % TX_BUFFER_SIZE;
            if (nextHead != txTail) { // Check if buffer is not full
                txBuffer[txHead] = data[i];
                txHead = nextHead;
            } else {
                // Buffer is full, handle overflow (e.g., discard data or wait)
            }
        }
    }
    
    // Start DMA transmission if not already in progress
    void startDMA(UART_HandleTypeDef *huart) {
        if (!txInProgress && txTail != txHead) {
            uint16_t length = (txHead > txTail) ? (txHead - txTail) : (TX_BUFFER_SIZE - txTail);
            HAL_UART_Transmit_DMA(huart, &txBuffer[txTail], length);
            txInProgress = 1;
        }
    }
    
    // Callback function when DMA transmission is complete
    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart->Instance == USART1) {
            txTail = (txTail + (huart->TxXferSize)) % TX_BUFFER_SIZE;
            txInProgress = 0;
            startDMA(huart);
        }
    }
    
    void sendData(uint8_t *data, uint16_t length) {
        enqueueTxData(data, length);
        startDMA(&huart1);
    }
    

    c. 主函数和初始化

    int main(void) {
        HAL_Init();
        SystemClock_Config(); // 由 CubeMX 生成的系统时钟配置函数
        MX_USART1_UART_Init(); // 由 CubeMX 生成的 UART 初始化函数
    
        // 主循环
        while (1) {
            uint8_t dataToSend[] = "Hello, UART DMA!\n";
            sendData(dataToSend, sizeof(dataToSend) - 1);
            HAL_Delay(1000); // 发送间隔
        }
    }
    

    解释
    环形缓冲区:使用 txBuffer 存储待发送的数据,通过 txHead 和 txTail 管理缓冲区的头尾位置。
    DMA 传输:当缓冲区有数据且没有传输正在进行时,启动 DMA 传输。传输完成后,更新 txTail 并检查是否有更多数据需要传输。
    避免丢帧:通过合理管理缓冲区和 DMA 传输,确保数据按顺序传输,减少丢帧风险。

    优点
    高效传输:利用 DMA 驱动高效传输大量数据。
    低延迟:环形缓冲区确保数据及时传输,减少传输延迟。
    灵活管理:可以根据需要调整缓冲区大小和传输逻辑,适应不同的应用场景。

    总结

    要提高 HAL_UART_Transmit 函数的执行速度并尽量避免丢帧,可以采取以下策略:

    使用非阻塞传输
    中断驱动模式。
    DMA 驱动模式。

    优化缓冲区管理
    使用环形缓冲区。
    增大缓冲区容量。

    提高 UART 配置效率
    增加波特率。
    优化数据位、停止位和奇偶校验设置。

    优化系统和任务管理
    提高 UART 中断优先级。
    合理安排任务优先级(在 RTOS 环境下)。

    采用双缓冲或更高效的传输函数
    实现双缓冲技术。
    直接操作寄存器或使用轻量级驱动。

    系统时钟优化
    提高系统时钟频率。
    确保系统时钟配置稳定。
    通过结合上述方法,可以显著提升 UART 传输性能,确保数据高效、稳定地传输,减少丢帧风险。

    作者:stone_hefei

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32提高串口发送函数执行速度并避免丢帧方法

    发表回复