[STM32F4] SPI Bootloader 隔一条命令就执行失败

[复制链接]
40|2
小库里 发表于 2026-9-17 15:24 | 显示全部楼层 |阅读模式
我在 Nucleo‑F446ZE 开发板上使用 SPI 内置 Bootloader 下发命令时每隔一条命令就收不到应答,奇偶交替,一条正常、一条失败。
以 GET_VERSION命令为例,第一次执行的收发情况如下:

MOSI(主机输出) MISO(从机输出)
0x5A       0xA5
0x01       0xA5
0xFE       0xA5

第二次再发送同一命令,通信就全部正常:

MOSI(主机输出) MISO(从机输出)
0x5A       0x79  // 帧起始应答
0x01       0x79  // 命令字节应答
0xFE       0x79  // 命令取反字节应答
0x00       0x79  // 应答帧
0x00       0x79
0x79       0x79
0x00       0x79  // 哑读
0x00       0x11  // 版本号
0x00       0x79  // 应答帧
0x00       0x79
0x79       0x79

很奇怪,上一条命令明明已经以 0x79 应答正常结束;但是紧接着再发送下一条命令起始字节 0x5A 的时候,从机返回的却是 0xA5,而不是0x79。
执行 GET以及 ERASE命令也会出现完全相同的故障。

才没有脸红 发表于 2026-9-17 15:37 | 显示全部楼层
0xA5 不是 NACK,它是 STM32 SPI 从机在发送寄存器为空时自动发出的空闲字节,属于“忙”状态而非错误响应。你在同步帧阶段收到它,说明从机还没准备好应答,而不是拒绝命令。

classroom 发表于 2026-9-17 17:10 | 显示全部楼层
AN4286 文档里确实写了命令帧第三字节应为 0x79,但根据 ST 社区里同样的案例,这个返回值在实际通信中并不总是出现,命令依然能被正确接受和处理。文档描述和固件实现之间可能存在偏差。
cr315 发表于 2026-9-17 18:40 | 显示全部楼层
你遇到的“隔一条命令失败”现象,根源在于主机的帧解析逻辑:你在等待 0x79 作为 ACK,但第一轮同步帧的第三个字节返回 0xA5 时,你把这次通信判定为失败并中止了,而从机其实已经收到了完整的 0x5A/0x01/0xFE 并进入了等待下一阶段的状态。
duo点 发表于 2026-9-17 19:00 | 显示全部楼层
SPI 是主从架构,从机无法主动“卡住”主机。真正的问题往往出在主机一侧的时序处理上——当从机发出 0xA5 忙字节后,主机需要继续发送 0x79 来“释放”从机,让它继续输出真正的 ACK 或数据。
flycamelaaa 发表于 2026-9-17 20:22 | 显示全部楼层
有一个容易被忽略的细节:STM32 的 SPI 从机在每次回复之前,移位寄存器里还残留着上一次的忙字节模式 0xA5。这就是为什么 AN4286 要求主机在读取任何数据前先发一个 dummy 字节——它是在推走那个残留的 0xA5,而不是在“等待”什么。
jcky001 发表于 2026-9-17 21:42 | 显示全部楼层
你观察到的“奇数条命令失败”规律,本质上是主机状态机在两次命令之间没有正确复位。第一次失败后,主机重试逻辑让状态机恰好落在了正确的位置,所以第二次同一命令能跑通,但紧接着第三次又掉回错误状态。
onlycook 发表于 2026-9-17 22:55 | 显示全部楼层
有人在 ST 社区里给出了和你完全一致的波形和故障描述,最后的结论是:主机不应该把同步阶段第三个字节的 0xA5 当作错误,因为 AN4286 中 Figure 4 对“SPI command frame”的绘图与实际行为不完全一致。
powerantone 发表于 2026-9-18 10:11 | 显示全部楼层
解决这个问题的实用思路是:在发送 0x5A/命令码/反码之后,主机不要盯着第三个字节找 0x79。直接从命令帧的应答阶段开始判断,或者像那位工程师一样,在第三个字节返回非 0x79 时重发命令,虽然这会让“每条命令执行两次”看起来有点怪,但功能是正常的。
埃娃 发表于 2026-9-18 11:50 | 显示全部楼层
看来你这个问题是主机状态机没复位,可以尝试在发送下一条命令前加入dummy read操作,清除从机移位寄存器里的残留数据。
probedog 发表于 2026-9-18 12:25 | 显示全部楼层
如果你的主机代码是在同步帧结束后立即检查 ACK,那 0xA5 的出现时机就很关键。AN4286 的 Figure 3 其实暗示了:0x5A 发出后从机需要一段时间同步波特率,这期间 MISO 输出的就是 0xA5,主机应该忽略它,而不是把它当作帧内容。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

217

主题

218

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0