两个 stm32 通过 SPI 进行通信,一主一从,但从机不能使用 CubeMX 的默认配置,不然会被带进坑……
遇到问题
目前我两个 stm32f4 芯片通过 SPI 进行主从通信,但从机获取的第一帧数据会丢失一个位,其配置如下:
主机:
- CPOL = 0,CPHA = 0
- 软件片选
从机:
- CPOL = 0,CPHA = 0
- 硬件片选
其现象如下:
- 当主机启动,第一次发送
0xA5
时,从机会接收到0xD2
- 当主机启动,第一次发送
0x53
时,从机会接收到0x29
经过二进制对比可以发现:从机接收到的数据相比主机右移了一位,也就是说从机相比主机更早的接收到了一个时钟。
排查
要找到这个问题,首先就需要缩小范围,判断是主机的问题还是从机的问题。
逻辑分析仪抓取主机发送时序如下:
可以看到,SCK 在 MOSI 发送数据前,居然被拉高了!
前面的配置中,CPOL = 0,那么此时 SCK 应该保持低电平才对。
那可以猜想:从机判断 SCK 拉高了,误认为这是一个信号,所以从机会比主机提前接收一个 bit。
解决
有以下几种解决办法:
配置管脚状态
既然主机会莫名其妙的提前将 SCK 拉高,那么我们在从机端也可以将 SCK 管脚配置为 GPIO_PULLDOWN
模式(默认 CubeMX 生成的代码是 GPIO_NOPULL
):
1 | // SCK Pin should be pulled down when CPOL = 0 |
经测试,这下就可以正常稳定的通信了。
在解决后,我尝试搜索是否别人也遇到了这个问题,还是我这个是个例。
最终发送在stackexchange 上也遇到了同样的问题,而且其逻辑分析仪结果与我的一致,看来这个是 ST 的锅了……
配置时钟极性
既然主机会莫名其妙的提前将 SCK 拉高,那么我们也可以将主从机 SCK 极性配置为高,已掩盖掉此问题:
1 | hspi3.Instance = SPI3; |
这个经过测试,也是可以稳定通信的。