You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 G070 SPI DMA循环模式接收数据偏移问题求助

SPI DMA循环模式+双缓冲首次传输偏移问题分析

硬件与软件环境

  • MCU:STM32 G070CB(64MHz主频)
  • 通信链路:两块PCB分别作为SPI Master/Slave,通过TI SN65LVDS系列芯片转换实现4线SPI(CSn、MISO、MOSI、SCK)通信
  • 软件栈:STM32 HAL库,使用SPI DMA收发函数
  • 传输逻辑:
    • Master发送20字节数组(内容为0-19,最后一位为递增Tx计数器)
    • Slave返回20字节数组(内容为19-0,第一位为传输计数器)
    • 通信触发:通过UART同步,Slave就绪后Master才启动传输

问题现象

  • Slave使用DMA普通模式时,通信完全正常
  • Slave切换为DMA循环模式+双缓冲技术后:
    • Master接收的数组固定偏移3-4字节,但Slave接收数据完全正常
    • 复位Slave后,通信恢复同步且稳定运行
  • 该现象与SPI时钟频率(1MHz8MHz)、传输触发频率(10Hz5kHz)无关
  • Slave调用HAL_SPI_TransmitReceive_DMA返回HAL_OK后,已延迟100ms才通过UART通知Master就绪

问题分析与解答

1. 为何Slave的SPI Tx DMA首次传输错过前3-4个时钟周期,Rx DMA正常,后续同步?

这是STM32 G0系列DMA循环模式+双缓冲初始化阶段的时序对齐问题:

  • 配置DMA循环模式+双缓冲时,HAL库会在初始化阶段预加载第二缓冲区地址到DMA寄存器,但此时SPI Tx FIFO可能未完全就绪(比如复位后默认空状态,DMA启动时序与SPI外设时钟使能、FIFO填充存在微小延迟)。
  • Slave的SPI Rx DMA由Master的SCK时钟被动触发,只要SCK到来就能立即捕获数据;但Tx DMA是主动填充FIFO,首次启动时,DMA的请求响应、缓冲区地址加载存在几个时钟周期的滞后,导致前几个SCK周期内SPI Tx FIFO为空,只能发送默认电平或旧数据,进而造成Master接收的前几个字节偏移。
  • 首次传输完成后,DMA循环模式已完成缓冲区切换,后续FIFO填充时序与SPI时钟完全对齐,因此同步恢复正常。

2. 为何复位Slave后能正常同步,代码无差异?

复位操作会强制重置所有外设和DMA寄存器到默认状态,消除了初始化阶段的时序残留:

  • 复位后,SPI外设、DMA控制器的所有寄存器(包括FIFO状态、缓冲区地址指针、请求标志位)都被清零,此时调用HAL_SPI_TransmitReceive_DMA时,DMA初始化与SPI外设就绪状态完全匹配。
  • 非复位情况下,若之前运行过DMA普通模式,部分DMA寄存器(比如上次传输的残留地址、请求标志位)可能未被完全清零,导致循环模式初始化时出现时序偏移;而复位后不存在这些残留状态,初始化时序完全对齐。

3. 为何仅在DMA循环模式下出现该问题,普通模式无异常?

DMA普通模式和循环模式的初始化与运行机制存在本质差异:

  • 普通模式:每次传输完成后DMA自动停止,且不会预加载下一个缓冲区地址。调用HAL_SPI_TransmitReceive_DMA时,DMA会等待SPI外设完全就绪后才开始填充FIFO,时序完全同步,不会出现滞后。
  • 循环模式+双缓冲:DMA会持续运行,且初始化阶段就预加载两个缓冲区的地址,此时SPI外设的FIFO可能还未进入就绪状态(比如外设时钟刚使能,FIFO同步逻辑未稳定),导致首次传输的DMA请求响应滞后于SPI时钟,从而出现字节偏移。

内容的提问来源于stack exchange,提问作者Chris_B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:52:24