如何用STM32的DMA双缓冲模式实现无中断延迟的ADC连续采样?

· 1 浏览

回答(4)

实测建议:将缓冲区大小设为采样率/中断频率的整数倍,例如10kHz采样,缓冲区256点,则中断频率约39Hz,CPU占用极低,适合高速连续采样。
STM32实战派 · 2026-08-27
注意:双缓冲模式下,DMA的NDTR寄存器会递减,但切换是硬件自动的,你只需在回调中读取当前活动缓冲区索引(通过HAL_DMA_GetState或自定义标志),避免数据覆盖。
代码工匠小王 · 2026-08-27
补充:若追求极致无延迟,可关闭DMA中断,改用定时器更新事件触发一个低优先级中断,仅用于切换缓冲区指针,但需确保处理时间远小于采样周期。
嵌入式老张 · 2026-08-27
核心思路:利用DMA双缓冲(也叫乒乓缓冲)配合定时器触发ADC,让DMA在两个缓冲区之间交替填充,同时CPU或主循环只处理非活动缓冲区,从而避免中断频繁打断采样。具体实操:1)配置ADC为连续扫描模式,触发源选定时器(如TIM1/8)的更新事件,确保采样率稳定;2)DMA设为循环模式,外设地址固定为ADC->DR,内存地址指向两个缓冲区(如buf1和buf2),数据宽度半字(16位),方向外设到内存;3)启用DMA的双缓冲模式(通过DMA_SxCR的DBM位,或使用HAL的HAL_DMAEx_MultiBufferStart函数),并设置两个内存地址;4)在DMA传输完成回调(或主循环轮询NDTR变化)中,切换当前处理缓冲区,但注意:双缓冲模式下,DMA会自动切换,无需手动干预,只需在回调中标记哪个缓冲区已满。关键点:为避免延迟,不要在每个采样点都进中断,而是等一个缓冲区填满(如256个样本)才触发一次中断,这样中断频率降低,且处理时间充裕。建议使用HAL库的HAL_ADC_Start_DMA配合HAL_DMAEx_MultiBufferStart,并注意缓冲区大小需为2的幂次,且对齐到32字节。
mcuku 阿沐 · 2026-08-27