项目场景:
本人最近在做一个STM32F103C8T6的两个SPI模块自通信实验,旨在验证SPI收发数据的正确性。即事先设定好两个SPI模块发送的值,通过ST-LINK单步调试观察单片机内部寄存器的值。待发送的数据如下:
同时定义两个SPI的接收数组:
问题描述
单片机全速运行时,发现传输结果中出现了数据错误:
下图为单步调试中,两个SPI模块数组的接收内容:
很明显和发送数据不匹配。
原因分析:
参考了网上的一些解决方案,有人说是因为在watch窗口中观察了SPIx->DR或者SPIx->SR导致发送和接收会出问题,试了一下,接收数据还是与发送数据不匹配。后来参考了这篇博客https://amobbs.com/thread-5559839-1-1.html,受到启发,更改了主机和从机的时钟极性和时钟相位:
原先导致出错的设置:
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
更改之后的设置:
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; /* 更改在此处,使主机和从机在时钟下降沿读取数据 */
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
实验结果:
可以看到SPI1和SPI2实现了正确的数据接收。
实验总结:
这里我更改了
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; 两个SPI模块就实现了正确的数据接收。
为什么更改CPHA位就能实现正确的数据接收,具体原因还未深入研究,可能是MOSI和MISO管脚的数据在SCLK时钟下降沿比较稳定,或者说SCLK时钟信号的下降沿毛刺比较小等。
希望能帮助更多遇到同样问题的同学,也欢迎大家留言讨论~