STM32F0系列芯片SPI发送一字节数据却输出16个CLK时钟的解决办法
问题
上一个项目在用寄存器操作STM32F0芯片的SPI_DR寄存器的时候,发现一个问题:
我给DR寄存器赋值一个uint8_t一字节大小的数据,SPI引脚能正确输出数据和时钟,但前面八位正确的数据输出完成后,时钟CLK没有停下来,又紧接着输出了八个时钟脉冲
也就是原数据0xfe 变成了十六位的 0xfe00 , 导致时序错误,使用逻辑分析才得以检查出来
为什么
去国外的st论坛转了一圈,发现有几个老外也是遇到了相同的问题,但他们是使用正确的固件库函数解决的,这并不是我想要找到的寄存器解决方法
后来又认真阅读了一次F030的数据手册,又仔细看了很久的HAL库底层代码,终于找到了问题所在:
如果你要spi输出一个字节八个时钟的数据,应该只操作SPI_DR寄存器的低八位,什么意思呢?
DR寄存器是16位的,如果你直接SPI1->DR = 0x85 ; 这样的操作是不正确的,你的数据会变成0x0085之后赋值给DR寄存器,也就是操作了16位,所以STM32会输出16个时钟脉冲
怎么办
那么看看我是怎么改的:
1 void SPI_WriteByte(uint8_t BYTE) 2 { 3 //将DR寄存器的地址向后偏移1字节再赋值,不能操作高八位只能赋值给低八位 4 *((uint8_t*)&(SPI1->DR) + 1 ) = BYTE ; 5 while(SPI1->SR & 0x80);//等待BSY为空闲 6 }
我们先找到DR寄存器的地址,再用一个八位的指针指向这个地址,现在指向的是DR寄存器的开头,那么指针+1,指针指向了DR寄存器的低八位
这时候给指针指向的地址赋值0x85,那么这个字节就会放入DR低八位的空间内,而不是操作整个16位DR寄存器
去看看那SPI的输出把,哈哈,正常了,八位数据对应八个时钟然后结束 ;
嘻嘻
希望能帮助到在学习或者工作中遇到同样问题的朋友