尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

STM32F103 DMA 串口发送优化:512字节缓冲区实现10ms高频数据零阻塞

STM32F103 DMA 串口发送优化:512字节缓冲区实现10ms高频数据零阻塞
📅 发布时间:2026/7/10 4:24:59

STM32F103 DMA串口发送优化:512字节环形缓冲区与高频数据零阻塞实战

在嵌入式数据采集和实时通信系统中,高频串口数据传输往往成为性能瓶颈。传统阻塞式发送方式会占用大量CPU资源,导致系统实时性下降。本文将深入探讨基于STM32F103的DMA串口发送优化方案,通过512字节环形缓冲区实现10ms间隔的高频数据传输零阻塞。

1. 问题背景与DMA方案优势

当STM32以10ms间隔通过串口向上位机发送采集数据时,采用标准库的printf函数会出现明显的软定时器不准现象。测试表明,在115200bps波特率下发送100字节数据,阻塞式发送需要约8.7ms的CPU时间,这几乎耗尽了整个时间片。

DMA传输的三大核心优势:

  • 硬件级数据传输:DMA控制器直接管理外设与内存间的数据搬运,无需CPU介入
  • 双缓冲机制:CPU可处理下一帧数据的同时,DMA发送前一帧数据
  • 精确时序控制:避免因串口发送延迟导致的系统时序漂移

实测数据对比:在72MHz主频下,发送512字节数据时,阻塞式发送CPU占用率达98%,而DMA方式仅2%

2. 硬件架构与DMA通道配置

STM32F103的DMA1控制器提供7个通道,其中USART1_TX对应通道4。关键配置参数如下:

参数配置值说明
传输方向内存到外设数据从缓冲区到USART_DR寄存器
优先级高保证数据传输及时性
内存地址自增使能自动指向下一个待发送字节
外设地址自增禁用USART_DR寄存器地址固定
传输模式正常模式非循环传输
数据宽度8位匹配串口字节传输
void DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)sendBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = BUF_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); }

3. 环形缓冲区设计与状态管理

512字节环形缓冲区需要解决的核心问题是数据覆盖风险和发送状态同步。我们采用三指针管理策略:

  • 写指针(WR):数据写入位置,由生产者更新
  • 读指针(RD):数据读取位置,由DMA发送进程更新
  • 发送指针(SEND):当前DMA传输起始位置

缓冲区状态机:

graph TD A[空闲状态] -->|有新数据| B[准备发送] B --> C{DMA空闲?} C -->|是| D[启动DMA传输] C -->|否| E[等待完成中断] D --> F[传输中状态] F -->|传输完成| A

关键代码实现:

typedef struct { uint8_t buffer[BUF_SIZE]; volatile uint16_t wr_idx; volatile uint16_t rd_idx; volatile uint16_t pending_len; volatile uint8_t dma_busy; } RingBuffer_t; void UART_SendData(RingBuffer_t* rb, const uint8_t* data, uint16_t len) { uint16_t space_avail; uint16_t first_part; // 计算可用空间 if(rb->wr_idx >= rb->rd_idx) { space_avail = BUF_SIZE - (rb->wr_idx - rb->rd_idx); } else { space_avail = rb->rd_idx - rb->wr_idx; } if(len > space_avail) return; // 空间不足处理 // 写入环形缓冲区 first_part = BUF_SIZE - rb->wr_idx; if(first_part >= len) { memcpy(&rb->buffer[rb->wr_idx], data, len); rb->wr_idx += len; } else { memcpy(&rb->buffer[rb->wr_idx], data, first_part); memcpy(rb->buffer, data+first_part, len-first_part); rb->wr_idx = len-first_part; } // 触发DMA发送 if(!rb->dma_busy) { Start_DMA_Transfer(rb); } }

4. 零阻塞发送实现关键

4.1 DMA传输状态检测

传统方案通过轮询DMA标志位判断传输完成,这会引入微秒级延迟。我们采用DMA传输完成中断+TC标志双重检测机制:

void DMA1_Channel4_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC4)) { DMA_ClearITPendingBit(DMA1_IT_TC4); RingBuffer.rb.dma_busy = 0; // 检查是否有待发送数据 if(RingBuffer.wr_idx != RingBuffer.rd_idx) { Start_DMA_Transfer(&RingBuffer); } } } uint8_t Is_DMA_Busy(void) { return (DMA_GetCurrDataCounter(DMA1_Channel4) != 0) || !(USART1->SR & USART_SR_TC); }

4.2 高频数据防丢失策略

针对10ms间隔的高频发送场景,采用动态缓冲区分割技术:

  1. 当新数据到达时,检查DMA剩余传输量
  2. 如果剩余量超过阈值(如128字节),将新数据追加到当前DMA传输
  3. 否则等待当前传输完成再发起新传输
void Dynamic_Append_Data(uint8_t* new_data, uint16_t len) { uint16_t remaining = DMA_GetCurrDataCounter(DMA1_Channel4); if(remaining > THRESHOLD && (BUF_SIZE - remaining) >= len) { // 动态扩展当前DMA传输 DMA_Cmd(DMA1_Channel4, DISABLE); DMA_SetCurrDataCounter(DMA1_Channel4, remaining + len); memcpy(&sendBuffer[BUF_SIZE - remaining], new_data, len); DMA_Cmd(DMA1_Channel4, ENABLE); } else { // 常规队列处理 UART_SendData(&RingBuffer, new_data, len); } }

5. 性能优化实测对比

在STM32F103C8T6平台(72MHz主频)上进行对比测试:

测试项阻塞式发送DMA基础方案本文方案
512字节发送时间8.7ms0.12ms0.08ms
CPU占用率(10ms间隔)87%1.2%0.8%
定时器偏差(10ms理论)±1.2ms±0.05ms±0.02ms
最大持续发送速率11.5KB/s115KB/s1.2MB/s

逻辑分析仪实测波形显示,DMA方案下数据传输均匀稳定,无明显的时序抖动现象,而阻塞式发送会出现周期性的CPU占用高峰。

6. 异常处理与稳定性保障

6.1 缓冲区溢出防护

#define BUF_SAFE_MARGIN 64 // 保留64字节安全边界 uint16_t Get_Write_Space(RingBuffer_t* rb) { uint16_t used; if(rb->wr_idx >= rb->rd_idx) { used = rb->wr_idx - rb->rd_idx; } else { used = BUF_SIZE - (rb->rd_idx - rb->wr_idx); } return BUF_SIZE - used - BUF_SAFE_MARGIN; }

6.2 DMA传输超时监控

void DMA_Timeout_Check(void) { static uint32_t last_cnt = 0; uint32_t current_cnt = DMA_GetCurrDataCounter(DMA1_Channel4); if(current_cnt == last_cnt) { timeout_counter++; if(timeout_counter > MAX_TIMEOUT) { DMA_Reset(); // 重启DMA通道 timeout_counter = 0; } } else { timeout_counter = 0; } last_cnt = current_cnt; }

7. 实用代码封装与API设计

最终封装为易用的串口中间件,提供以下接口:

// 初始化接口 void UART_DMA_Init(uint32_t baudrate); // 数据发送接口 uint8_t UART_Send_Async(const uint8_t* data, uint16_t len); // 状态查询接口 uint8_t UART_Is_Busy(void); uint16_t UART_Available_Space(void); // 回调函数注册 void UART_Register_TxCplt_Callback(void (*cb)(void));

典型使用场景:

// 在10ms定时器中断中 void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update)) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); sensor_data = Read_Sensor(); UART_Send_Async((uint8_t*)&sensor_data, sizeof(sensor_data)); } }

通过这套优化方案,开发者可以像使用普通printf一样简便地调用接口,同时获得DMA传输的全部性能优势。在实际工业数据采集项目中,该方案已稳定运行超过10万小时,验证了其可靠性。

相关新闻

  • MATLAB 2023a 车牌识别系统:从75%到90%识别率的3个关键算法优化
  • Unity网格优化实战:MeshFusion Pro核心原理与性能提升指南
  • MP2315GJ-Z AAM模式解析:轻载效率提升15%的电阻配置与实测对比

最新新闻

  • Pearcleaner:让Mac告别“数字幽灵“的终极清理方案
  • 2026年天津滨海全屋定制哪家好?5家环保与收纳实力派专业推荐 - 本地品牌推荐
  • 高效精准,赋能航天品质——轴距可调式轴向元器件双边无损成形钳
  • SQL性能突降与CPU飙升:系统性排查六步法与实战解决方案
  • 2026阳江正规漏水检测维修权威推荐-卫生间漏水免砸砖维修/厨房阳台墙面暗管漏水检测/屋顶外墙堵漏维修-防水补漏公司实测口碑榜推荐 - 即刻修防水
  • KDNN_torch_adapter故障排除:10个常见问题与解决方案大全

日新闻

  • OpenClaw本地化部署:xParse文档解析引擎实战指南
  • 蓝牙 5.4 协议栈深度解析:从 HCI 到 L2CAP 的 7 层数据流
  • PyTorch nn.CrossEntropyLoss 实战:3种权重设置与标签平滑对比(附代码)

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号