STM32 使用 DMA 与环形缓冲区接收不定长串口数据时,如何精确处理帧边界与半满中断竞态?

· 4 浏览

回答(4)

若使用RTOS,可将DMA中断中只发送信号量,由任务处理数据,利用任务调度天然避免竞态,但需注意中断延迟。
FreeRTOS爱好者 · 2026-08-27
建议使用DMA的传输完成中断(全满)来触发帧解析,半满仅用于搬运,这样可简化竞态处理,但需保证缓冲区足够大。
码农小张 · 2026-08-27
可以用空闲中断作为帧结束标志,配合DMA半满中断做数据搬运,但注意空闲中断优先级应高于DMA中断,避免数据覆盖。
嵌入式老周 · 2026-08-27
处理帧边界与半满中断竞态,核心是理解DMA半满/全满中断与空闲中断的协作。建议采用“DMA双缓冲+空闲中断”方案:配置DMA为循环模式,使能半传输和传输完成中断,同时开启USART空闲中断。在空闲中断中,读取DMA当前数据指针(DMA_GetCurrDataCounter)与缓冲区基址,计算已接收数据长度,并更新读索引;在半满/全满中断中,仅更新读索引,不处理帧解析。关键竞态在于:空闲中断可能发生在半满中断处理期间,导致数据被覆盖。解决方法是:在中断服务程序中,先关DMA中断(或使用临界区),读取DMA计数器并拷贝数据到应用缓冲区,再恢复中断。同时,使用环形缓冲区时,需保证读索引与写索引的原子更新(如使用volatile或关中断)。建议将帧解析放在主循环,中断只负责搬运数据,避免在中断中做复杂处理。实操上,可先用逻辑分析仪验证时序,再调整DMA缓冲区大小(建议为最大帧长的2倍以上)以降低竞态概率。
mcuku 阿沐 · 2026-08-27