STM32 使用 DMA 传输时,如何精确计算并避免缓冲区溢出(含环形缓冲实现)

· 2 浏览

回答(4)

考虑使用DMA的传输完成和半传输中断,实现双缓冲处理。这样即使主循环繁忙,也能及时搬移数据,避免覆盖。记得在中断中快速更新读指针,并清标志。
STM32爱好者 · 2026-08-27
环形缓冲大小选2的幂,用位与代替取模,效率高。同时,DMA传输长度设为缓冲区大小,配合循环模式,硬件自动回绕,软件只需管理读写指针差值。
码农小刘 · 2026-08-27
用NDTR寄存器实时计算:实际写入位置 = 缓冲区大小 - NDTR。每次中断或轮询时更新写指针,确保读指针不超越写指针。建议在临界区禁用中断保护指针更新。
嵌入式老张 · 2026-08-27
精确计算DMA缓冲区溢出,核心是监控DMA当前传输位置(NDTR寄存器)与软件读写指针的差值。对于环形缓冲,建议使用2的幂次方大小(如256、512),便于指针回绕时用位与操作(& (size-1))替代取模。实现时,DMA外设地址指向外设寄存器,内存地址指向环形缓冲,设置循环模式(Circular)。软件侧维护读指针(read_idx)和写指针(write_idx),写指针由DMA硬件更新(通过DMA中断或轮询读取NDTR推算实际写入位置)。关键计算:可用空间 = (write_idx - read_idx + size) % size,当可用空间小于单次DMA突发长度时,暂停DMA或丢弃数据。为避免溢出,建议在DMA传输完成中断中同步更新逻辑写指针,并预留至少一个完整数据包的空间作为安全余量。实操中,可开启DMA传输半完成和完成中断,分两段处理数据,降低延迟。若使用STM32CubeMX,注意配置DMA为Circular模式,并启用FIFO(若支持)以缓冲突发。
mcuku 阿沐 · 2026-08-27