STM32F4 使用DMA+双缓冲采集ADC时,如何精确计算触发延迟并避免缓存撕裂?

· 1 浏览

回答(4)

双缓冲撕裂的根源是CPU和DMA同时访问同一内存。可用CMSIS的__LDREX/__STREX实现无锁环形队列,或直接让DMA写SRAM,CPU只读,避免缓存一致性问题。
嵌入式小飞侠 · 2026-08-27
计算延迟时别忘了ADC的采样时间(可设15周期),总延迟=触发同步+采样+转换+DMA搬运。用逻辑分析仪抓GPIO翻转,实测校准比理论更可靠。
芯海拾贝 · 2026-08-27
建议用DMA的FIFO模式(阈值设为半字),可减少总线竞争,延迟更稳定。实测FIFO开启后,DMA响应抖动从±3周期降到±1周期。
嵌入式老周 · 2026-08-27
精确计算触发延迟需从硬件链路拆解:ADC采样时钟(如ADCCLK=APB2/4=21MHz)决定单次转换时间(如12位+3周期=15/21MHz≈714ns),DMA响应延迟约2-3个AHB时钟周期(~20ns),双缓冲切换由DMA半/全传输中断触发,软件开销(中断入栈+标志位操作)约1-2μs。要避免缓存撕裂,核心是使用DMA的循环模式+双缓冲(Memory-to-Memory模式),并利用硬件半传输中断(HT)和传输完成中断(TC)分别切换缓冲区,确保在DMA写入当前缓冲时,CPU只读另一缓冲。实操建议:1) 配置DMA为循环模式,双缓冲地址对齐到32字节;2) 在HT/TC中断中仅置标志位,主循环中处理数据;3) 若需精确触发延迟,可启用ADC的注入组并设置外部触发(如定时器TRGO),用定时器计数同步,延迟=定时器触发到ADC采样保持的固定周期(约1.5个ADCCLK)+DMA搬运时间。避免撕裂的终极方案是使用“乒乓缓冲”+内存屏障(__DMB),并在切换前禁用DMA中断,确保数据一致性。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

📊 ADC 转换