[应用相关] [学习笔记] STM32 SPI的特性和不足

[复制链接]
4390|1
 楼主| cruelfox 发表于 2018-12-28 23:56 | 显示全部楼层 |阅读模式
本帖最后由 cruelfox 于 2018-12-28 22:24 编辑

参考资料: RM0351 STM32L4x6 Reference Manual  第38章节

SPI是很基本的串行通信协议之一,STM32具有硬件SPI模块(有的还带有I2S模式,这里不考虑),可是好用否?通过对手册的学习,我梳理一下平常用得到的如下特点:
(1) 支持常规的 SPI 信号:SCK/MISO/MOSI 三线全双工模式,可以作主机,也可以作从机。可配置时钟相位、空闲时的时钟状态、MSB或LSB在前的模式。
(2) 支持两线模式,可以用单条数据线实现收和发(半双工)
(3) 支持 4-bit 到 16-bit 的字长
(4) 具有NSS (Slave Select,即片选信号)管理,还可以借助它实现主从角色的自动切换。
(5) 可选的硬件CRC功能
(6) 带有FIFO, 支持DMA操作. 硬件状态查询和中断产生等功能等(属于应该有的)

最常见的连接方式是下图这样(如果是两个STM32用SPI通信)
spicomm.png
按照常规的理解,CPOL, CPHA, 字长等基本参数都容易设置,按寄存器说明配置就可以了。双向通信需要把接收和发送都允许。
但是 NSS 脚的使用,在SPI传输里面它并不是必须有的。没有 SS 信号,从机一直处于侦听状态,靠 SCK 实现字同步没有问题。启用 SS 信号,则从机只在 SS 为低时才会管 SCK 上的时钟信号。作为从机,将 CR1 中 SSM 位写1,则不再使用 NSS 脚的信号,而靠 CR1 中 SSI 位来代替,如下的叙述:
ssm1.png
作为主机时,对 NSS 脚有两种硬件操作方式:一是SSOE为1,它输出片选信号(但是并不是在有数据发送时变低,而是SPI硬件使能,即 CR1 的 SPE 打开就变低,即使没有数据传输。个人以为意义不大,用一个GPIO代替都够了);二是SSOE为0,它作为输入信号,用来判断总线冲突,这样允许多个主机同时连接(当然属于非标准的用法了)。

作主机时SCK信号的产生,有两种情况。一是双向通信或仅有发送时,向数据寄存器 DR 写数会自动启动传输,根据数据量产生若干个周期的 SCK 脉冲信号,然后结束。另一种情形是单向接收(包括半双工模式下的方向选择为接收)时,SCK信号会一直持续——不能控制SCK的脉冲个数,或者说传输量。因为在实际项目中用过,个人觉得这在半双工模式下是个缺憾。
rxonly.png

作为 SPI 主机,向数据寄存器DR写数据,开始一次传输,数据从 MOSI 脚逐位发送出去,然后从数据寄存器可以读到这一次同时从 MISO 脚收到的数据,这个行为是很明确的。但若作为从机,当外面有 SCK 信号来之前,必须将要发送的数据已写入数据寄存器DR(实际上是写入内部FIFO),才能正确地发送。 如果没有先写好,并且FIFO是空的,那么从 MOSI 发送出去的是什么数据呢?我在手册中没有看到相关的叙述。如果发送出去是全0倒好了,从我实际应用的结果来看,送出的是以前写过的数据,但不一定是最后一次写的数据。还有问题是,STM32 的 SPI 没有提供一个“把FIFO清空”的办法,这在FIFO中有数据但不想要的时候是有用的(我不想把整个SPI给Reset)

SPI 内部这个 FIFO 有4字节的容量,但是在 APB 总线上,DR 是一个16-bit的寄存器,同时又可以以8-bit模式访问。这里尤其要小心了。
fifo.png
比如常规的 8-bit 字长模式,向 DR 寄存器可以写两个字节,然后低字节先发送,高字节随后发送。在读取的时候,一次也能读FIFO中的两个字节数据。如果是像8位机那样,或者是为了软件写起来简单,一次只读或者写一个字节;以及只需要发送一个字节的数据时,怎么办?好在 DR 寄存器是可以字节(8-bit模式)访问的,那么下面这样写:
void SPI_transmit(char data)
{
   SPI1->DR = data;
}
正确吗?
我起初这么写,没有像我意料的那样工作。后来明白了 SPI1->DR 这是一个 16-bit 寄存器(可以看头文件中的结构体定义),上面这条语句会把 data 转换成 16-bit 的类型然后写到寄存器。读 DR 寄存器也会有类似的问题,而且一次读来的两个字节是否都是有效数据。在 SPI 收到数据的时候,依靠状态寄存器中 RXNE 位来指示 FIFO 有数据可以读取,而又取决于 FRXTH 的设置的阈值。 fiforead.png
fiforead2.png

SPI 的寄存器组挺少的,只要不涉及CRC功能,仅有 CR1, CR2, SR 和 DR 四个16-bit寄存器。 其中 SR 里面的状态位也比较少。我觉得缺少一个从机模式下 NSS 变高引起的“传输结束”标志,以及一个完整的字传输未完成时 NSS 变高的异常标志。SPI 不提供就只好用 EXTI 去代替了。总之,这个硬件的不足(不好用)之处在我看来还是有一些。



mmuuss586 发表于 2018-12-30 11:56 | 显示全部楼层
支持,感谢分享;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

50

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部