图4
这是一个32位的缓存,有利于SPI的连续工作。提高传输速率。
再来看一下F4的:
[attach]28685[/attach]
图5
F4仅有收发缓存器,也就是只有当上一数据发送完毕后再能写入下一个数据,这样就会造成发送的间断,降低数据传输速率。
两个单片机就在这两个方面有差别,但是,在使用的时候发现他们的DR寄存器操作有很大的差别,L476在8位及8位以下数据长度时,对DR写入数据后spj控制器会将DR认为是两个8位寄存器。先发送低8位的内容再发高8位。
[attach]28686[/attach]
图6
图6是用逻辑分析仪抓取的波形图,发送数据为0x0ff0,按理只有第8位会被发送,也就是0xf0;这里显然发送了16位的数据,而且可以看出,数据是0xf00f;正如我之前所说,先发送了低8位0xf0,再发送了0x0f;
再来看一下发生0x0000的情况:
[attach]28687[/attach]
图7
依然如此。
那么,SPI工作在别的数据长度呢?
6位模式,SPI1->DR=0x0303U;
[attach]28688[/attach]
图8
可见是发送了高8位和低8位数据中的低6位。
12位模式,SPI1->DR=0x0303U;
[attach]28689[/attach]
图9
显而易见,这是发送了0x0303的低12位,和上图两个六位有明显差别。
那么问题来了,我就想发送8位或更少的,咋办?
这个问题之前确实也困扰了我,费了两三个小时才想明白。
前面我们说到L476具有收发FIFO,就是这里搞的鬼。当你在8位模式下,你向DR寄存器(16位)写入一个值,那么就是更新了两个字节的数据,随后两字节数据都进入发送FIFO队列,逐一被发送。终于知道原因了,那么如何只更新一个字节呢?这就容易了,有两种方式:
①:直接对地址做8位操作,代码如下
[attach]28690[/attach]
图10
波形图:
[attach]28691[/attach]
图11
终于是有8个位了。
②:修改头文件,用共用体实现,修改如下
[attach]28692[/attach]
图12
[attach]28693[/attach]
图13
抓取波形
[attach]28694[/attach]
图14
发送是正确的。
我本人更倾向于第二种解决方法,用起来更方便。但是会破坏头文件,会导致你的程序的兼容性降低,代码移植起来就很不方便了。
好了,本次对SPI的评测解析就到这里了,欢迎大家和我一起讨论有关的问题,一起交流STM32的开发经验。我文中若有不对之处,也望大家能给指出,小弟不胜感激。