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的输出把,哈哈,正常了,八位数据对应八个时钟然后结束 ;

 

嘻嘻

希望能帮助到在学习或者工作中遇到同样问题的朋友

posted @ 2019-08-29 17:10  netube  阅读(2190)  评论(0编辑  收藏  举报