这次我们来学习SPI外设。
一.SPI外设简介
1.简介

也就是硬件收发时序,不用我们软件再去触发时序就可以了。
我们常用的是8位SPI数据帧高位先行,那么16位数据帧就是一次性可以发送16位数据。16位发送的波形和发送两次8位的波形一样。一个时钟频率交换一个bit,所以时钟频率一般体现的是单位是Hz,一般是bit/S。这里的时钟频率是Fpclk/一个分频系数。pclk就是外设时钟,APB2的外设时钟是72MHz,APB1的外设时钟是36MHZ。比如我们的SPI1是APB2外设,最大可支持72MHz/2=32MHz的时钟。
像我们之前I2C的频率最大只能支持400KHz。所以这里SPI的频率,比I2C快了90倍。
然后这里的兼容I2S是一种音频的协议。
二.框图
1.SPI简介框图(整体)

2.左上面部分

数据寄存器和移位寄存器配合的过程,和I2C通信一样,可以实现连续的数据流通信的效果。
右边的数据低位从MOSI一位一位的转移出去。然后MISO数据一位一位的从左边移入到左边的数据高位。显然移位寄存器是一个右移的状态,所以目前这里表示的是低位先行的配置,对于右下角有一个LSBFIRST的控制位,这一位可以控制是低位先行还是高位先行。

可以看一下手册,这里面说给0就发送MSB,MSB就是高位的意思。给1先发送SLB,LSB就是低位的意思。那么这里目前的状态就是1,低位先行

如果给0的话这个图就会变为高位先行输出从左边移动出去。输入从右边移进来。
交叉的电路主要是用来进行SPI主从模式的设置的,我们SPI可以做主机也可以做从机。做主机时候这个交叉就不用,从机时候MOSI为MO主机输出,MISO为主机输入。这就是做主机的情况

如果我们做从机的话,MOSI为SI从机输入,这时走下面的一路,输入到移位寄存器。同理MISO为SO从机输出,这时数据也走交叉的这一块输出到MISO。
接下来上下两个缓冲区是我们熟悉的设置这两个缓冲区就是数据寄存器DR,下面发送缓冲区就是发送数据寄存器TDR,上面接收缓存区就是接收数据RDR。和串口的一样TDR和RDR占用同一个地址,叫DR。
流程就是,写入一个数据到TDR,当移位寄存器没有数据移位时TDR的数据会立刻转移到移位寄存器开始移位,这个转入时刻,会置状态寄存器的TXE位为1。表示发送寄存器空,当我们检查TXE寄存器空之后,就可以下一个数据写入到TDR里面候着了,一旦上一个数据发完,下一个数据就可以立刻跟进。移位寄存器这里一旦有数据过来了就会自动产生时钟,将数据移位出去,在移出的过程中,MISO的数据也会移入,一旦数据移出完成,数据移入也完成了,这时移入的数据就会整体的从一位寄存器,转入到接收缓冲区RDR,这个时候会置状态寄存器的RXNE为1,表示接收寄存器非空,当我们检查RXNE为1后要尽快把数据从RDR读取出去。就可以实现连续接收。
和I2C对比的话
因为SPI是全双工,发送和接受同时进行,所以他的数据寄存器的发送和接受是分离的。而移位寄存器发送和接受可以共用。

然后看一下I2C的框图,因为I2C是半双工,发送和接受不会同时进行,所以他的数据寄存器和移位寄存器的发送和接受都是可以共用的。
和串口对比
因为串口是全双工,并且发送和接受可以异步进行

所以要求他的数据寄存器发送和接受是分离的,
移位寄存器发送和接受也得是分离的。同步通信移位寄存器不用分开,异步通信移位寄存器分开。
全双工发送和接收数据寄存器需要分开,半双工发送和接收数据寄存器不用分开。
全双工,发送和接收可同时进行,所以数据寄存器发送和接收需要分离。半双工,发送和接收不会同时进行,所以可共用。
3.右下角部分

控制逻辑部分,寄存器哪一位该干什么,控制哪一位会产生什么效果。
波特率发生器,内部就是一个预分频器。输入频率是72M或者36M,经过分频后,输出到SCK引脚当然这里生成的时钟,是和移位寄存器是同步的,每产生一个时钟,移入移出一个bit。

然后右边,CR1寄存器的三个位,BR0,BR1,BR2用来控制分频系数。

手册中可以看到BR2~0是波特率控制,这三位写入下面这些值,可以对PCLK时钟进行2~256的分频,分频之后就是SCK时钟。

然后LSB FIRST决定高位先行还是低位先行。

SPE是SPI使能,就是SPI_cmd函数。
BR配置波特率就是SCK时钟频率。
MSTR配置主从模式,1是主模式,0是从模式。我们一般用主模式。CPOL和CPHA,用来选择SPI的四种工作模式。

然后SR状态寄存器,最后的两位TXE,发送寄存器为空,RXNE接受寄存器非空。

CR2寄存器就是一些使能位。TXE中断使能,之后是TX的DMA使能和RX的DMA使能。

最后的NSS引脚,SS就是从机选择,低电平有效所以前面加了个N,这个NSS是用来实现多主多从的模型,我们直接用一个GPIO口来模拟从机就可以了。而且多从机的话SS还会有多个,所以这个硬件的NSS完成不了我们想要的操作。
三.SPI基本结构
1.简化版框图

移位寄存器高位移出去,通过GPIO移位到MOSI。从MOSI输出,这里显然这是SPI的主机,之后移入的数据从MISO进来,通过GPIO到移位寄存器的低位,这样循环8次就能实现主机和从机交换一个字节,然后TDR和RDR的配合,就可以实现连续的数据流了。
另外TDR数据整体转入移位数据寄存器时刻,置TXE标志位,移位寄存器数据整体转移到RDR时刻,置RXNE标志位。
数据控制器相当于一个管理员,控制着所有电路的运行。
SS的从机选择我们用GPIO模拟就可以,因为在一主多从模式下GPIO模拟的SS是最佳选择。
四.SPI传输时序图
1.主模式全双工连续传输
这个是借助缓冲区,数据一个接着一个,实现连续数据流的过程。但是这个过程比较复杂也不容易实现封装,所以在实际过程中,对性能没有极致的追求,我们更倾向使用非连续传输的数据图。我们简单了解一下啊。
(1)功能了解

首先CPOL=1,CPHA=1。示例使用的是SPI模式3。所以SCK默认是高电平。然后再第一个下降沿,MOSI和MISO移出数据,之后上升沿移入数据,依次进行。
第二行是MOSI和MISO的输出波形,跟随SCK时钟变化数据位依次出现,这里依次出现的是,b0,b1一直到b7。这里演示的是低位先行的模式,实际上SPI高位先行用的多一些
第三行是发送寄存器空标志位,第四行发送缓冲器SPI_DR实际上就是TDR,然后BSY是由硬件自动设置清除的。当有数据传输时,BUSY置1,没有数据传输时,BUSY置0。
上面的流程演示的是输出数据的现象,下面的流程演示的是输入数据的现象。之后是RXNE接受数据寄存器非空标志位。最后是接受缓冲器,读出SPI_DR,就是RDR。
(2)发送时序
首先SS置低电平,开始时序,再刚开始时,TXE为1,表示TDR空,可以写入数据,开始传输,之后软件写入0xF1至SPI_DR,0xF1就是要发送的数据

可以看到写入之后,TDR变为0xF1。同时TXE变为0,表示已经有数据了,那么此时TDR是等候区,移位寄存器才是真正的发送区,移位寄存器刚开始肯定没有数据,所以再等候区TDR里的F1就会立刻转入移位寄存器,开始发送。转入瞬间置TXE标志位为1表示发送寄存器空,可以继续写入数据了。此时移位寄存器有数据波形就自动开始生成,再移位产生F1波形的同时,等候区TDR是空的。为了移位完成时,数据能不间断的跟随,这里就要提早把下一个数据,放在TDR里面等着了。所以下面第二步的操作是,写入F1之后,软件等待TXE=1在这个位置,一旦TDR空了,我们就写入F2至SPI_DR,写入之后就可以看到,TDR内容就变成F2了。

也就是把下一个数据放在TDR里候着之后的二发送流程同理。F1产生波形后F2转入移位寄存器开始发送,这是TXE=1,我们尽快把下一个数据F3放在TDR里等着,软件等待TXE=1,之后写入F3到DR,写入之后TDR变为F3,最后如果我们只想要发送三个数据,F3转入移位寄存器之后TXE等于1,我们就不需要继续写入了,等F3波形完全发送之后,让TXE一直等于1,BUSY标志由硬件自动清除。这才表示波形发送完成了。
(3)接受的时序
因为SPI是全双工协议,发送的同时还有接受,所以再第一个字节发送完成后,第一个字节的接受也完成了。

接受到的数据1是A1,这时移位寄存器的数据,整体转移到RDR,RDR存储的就是A1,转入的同时,RXNE标志位也置1,表示收到数据了。我们的操作是,软件等待RXNE=1,等于1就表示收到数据了。然后从SPI_DR也即是RDR,读出数据A1,读取之后软件清除RXNE标志位,当下一个数据收到之后RXNE重新置1。我们检测到REXT=1时,就继续读出RDR,这是第二个数据A2。最后在最后一个数据的时序,完全产生后,数据3才能收到,所以数据3直到最后才能读出来。需要注意的是,当一个字节波形收到后,移位寄存器的数据,自动转存到RDR会覆盖原有的数据。所以我们读取RDR要及时。
2.主模式非连续传输
首先CPOL=1,CPHA=1。示例使用的是SPI模式3。所以SCK默认是高电平。然后再第一个下降沿,MOSI和MISO移出数据,之后上升沿移入数据,依次进行。

我想想发送数据时,如果检测到TXE数据等于1了。TDR为空就软件写入0xF1到SPI_DR,这时TDR的值变为F1,TXE变为0.目前移位寄存器也是空的所以这个F1会立刻转存到移位寄存器进行发送,然后波形产生,并且TXE置回1。表示你可以把下一个数据放在TDR里面候着了,这是相当于连续传输了,但是操作复杂,所以我们在TXE=1时这里不把数据再次写入,而是等待,等第一个字节时序结束,数据开始结束,等接受完数据,RXNE置1之后,先把第一个接受到的状态读出来,之后再写入下一个字节。这就是非连续传输的模式
3.模式对比
缺点就是在第一个字节位置,没有及时的,把下一个数据写入TDR候着,所以等到第一个字节时序完成后,第二个字节还没有送过来,那这个数据传输就会在这里等着,所以这里时钟和数据的时序再字节与字节之间,会产生间隙,从而减慢整体数据的传输速度。这个间隙再SCK频率低的时候影响不大,再SCK频率非常高得时候影响很大。
(1)256分频

这个SCK频率是72M/256=280khz。上面是SCK信号使用模式0,下面是SS信号表示模式1,这个波形是SPI非连续传输,交换5个字节的时序。虽然连续交换了字节,但是基本看不出字节与字节之间的间隙对吧。
(2)128分频

这个SCK频率是72M/128=560k,这时就可以明显的看出来,字节之间的间隙了,字节和字节之间并不是紧密的,这会降低整体字节的传输速度。
(3)64分频

这个SCK频率是72M/64=1Mhz多一点,因为频率增大,时间尺度缩小,这样看来间隙就更加明显了。
(4)2分频

这个SCK频率是72M/2=36MHz。虽然每个字节时钟看不完整,但是间隔还是看的很清楚的。
4.软硬件波形对比
(1)软件波形

(2)硬件波形

(3)对比
首先他们数据变化趋势肯定时一样的,采样得到的数据也是一样的,区别就和I2C一样,硬件波形数据线的变化是紧贴SCK边沿的,而软件波形数据线的变化,在边沿后有一些延迟。
5.手册阅读

SPI简介可以看到,在小容量和中容量产品上,不支持I2S音频协议。

这就是我们的SPI四种模式
CPOL时钟极性,决定空闲状态SCK默认电平。CPHA时钟相位,决定第一个边沿开始采样,还是第二个边沿开始采样。

主模式配置步骤。

对SPI的一些裁剪。把标准的SPI变为1条时钟线,和一条双向数据线。这其实就是半双工,或者一条单向数据线和一条时钟。

这个是可以在数据流后面加一个CRC校验码,用于确定数据有没有传输出错。

之后就是状态标志位。

控制寄存器就是用来配置电路的,我们初始化结构体也主要是来填写这些位。

各种模式都通过来写状态寄存器来实现。

然后控制寄存器CR2是一些中断使能,也是用于配置电路的。

状态寄存器SR主要记住的是TXE和RXNE。

数据寄存器DR,数据寄存器对应两个缓冲区,一个用于写,就是我们说的TDR,一个用于读,就是我们所说的RDR。