凡亿教育-小米
凡事用心,一起进步
打开APP
公司名片
凡亿专栏 | 高频面试题:SPI协议传输流程,四种模式怎么区别?
高频面试题:SPI协议传输流程,四种模式怎么区别?

雷猴啊,今天聊另一个高频的面试题:SPI。

 

这个考的概率也非常非常大,因为SPI用的实在是太多太多了,可以说80%的项目都会用到。

 

以前我刚做开发时,也很怕spi,同样是spi时序,这个器件可以,换一个器件就不行了。

 

也被这玩意儿折腾得想砸键盘。以为不就是几根线嘛,接上去时序按照spi的不就行了?

 

这种痛,只有搞过单片机通信的人才懂,其实就是spi四种模式搞的鬼。如果SPI协议的传输流程和这四种模式你没搞透,将来遇到的问题只会更多。

 

连个最基本的通信都搞不定,还怎么去驱动复杂的器件?怎么去实现更牛逼的功能?

 

读完这篇文章,你将彻底告别SPI模式选择困难症,拿到一个新的SPI器件,你就能快速找到它的模式信息,自信地在代码里配置正确,让你的设备顺利"对上话"。

 

好,不卖关子了,直接开整。

 

介于很多人对spi可能不太熟悉,先介绍一下,SPI(Serial Peripheral Interface)协议,中文叫串行外围接口。它是一种高速、全双工、同步通信总线。

 

注意关键词:同步、串行、全双工。

 

同步,意味着通信双方要靠同一根时钟线(SCK)来协调数据发送和接收的节奏。就像两个跳舞的人,得跟着同一个节拍器才能跳齐。

 

串行,意味着数据是一位一位地传输,而不是像并行通信那样同时能传几个数据。虽然速度可能不如并行,但引脚少啊,省资源。

 

全双工,理论上是可以在同一时刻既发送数据又接收数据。SPI有两根独立的数据线:MOSI(Master Out Slave In,主机输出,从机输入)和MISO(Master In Slave Out,主机输入,从机输出)。

 

主机通过MOSI发送数据给从机,从机通过MISO发送数据给主机。因为这两根线是分开的,所以理论上可以同时进行,实现全双工。但实际应用中,很多场景是主机发完命令从机再发数据,或者反之,表现得更像半双工。

 

除了SCK、MOSI、MISO,SPI通常还需要一根片选线(SS,Slave Select,或者叫CS,Chip Select)。

 

主机通过SS线来告诉某个特定的从机:“喂,说你呢,准备好,我要跟你通信了!” 

 

当主机需要跟多个从机通信时,每路从机都需要一个独立的SS线,主机通过拉低(通常是低电平有效)对应从机的SS线来选中它。未被选中的从机在高阻态,不参与通信。

97ee52458abdb5d412498c1ef39e23.jpg

 

理解SPI的传输流程,关键在于理解数据是怎么随着时钟脉冲一位一位地在MOSI和MISO线上“跑”的。

 

主机和从机都有一个移位寄存器(Shift Register)。发送方要发送一个字节(8个bit),它先把这8个bit装进自己的移位寄存器里。

 

接收方也准备一个空的移位寄存器等着。

 

通信开始时,主机拉低目标从机的SS线。然后,主机开始在SCK线上发送时钟脉冲。

 

每一个时钟脉冲到来时(具体是上升沿还是下降沿,取决于模式),发送方会把移位寄存器里的最高位(或者最低位,这取决于SPI的bit序设置,通常是MSB First,即最高位先行)“推”到数据线(MOSI或MISO)上。

 

同时,接收方会在此时刻从数据线(MISO或MOSI)上“读”入对方发送过来的一个bit,并把它“移”进自己的移位寄存器。

 

这个过程是同步进行的:发送方推一个bit出去的同时,接收方拉一个bit进来。就像两个人面对面,一个人把手里的球递出去,同时接过对方递过来的球。

 

这样重复8次,一个字节就传输完成了。发送方的移位寄存器清空了,接收方的移位寄存器里装满了对方发来的一个字节数据。

 

在同一个8个时钟周期内,主机通过MOSI发送了一个字节给从机,同时,从机也通过MISO发送了一个字节给主机(这个字节的内容可能是从机状态、之前操作的结果,或者仅仅是预设的填充值)。这就是为什么说是全双工,数据在两根线上是同时流动的。

 

当然,很多时候我们只关心其中一个方向的数据。比如主机发送一个命令,从机返回一个寄存器值。这时主机发送命令时,从机在MISO上发的是无效数据;

 

从机返回寄存器值时,主机在MOSI上发的可能是无效数据或者下一个命令的一部分。但物理上,数据流是同时进行的。

 

传输完一个字节或一组字节后,主机可以拉高SS线,结束本次通信。

 

下面聊下SPI的四种模式:CPOL与CPHA的组合

 

SPI之所以让很多人头疼,很大一部分原因就在于它的四种模式。这四种模式由两个参数决定:CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)。

 

•CPOL:时钟极性

CPOL决定了时钟线SCK在空闲状态(SS线为高电平,没有通信时)时的电平。

 

CPOL = 0:SCK空闲时为低电平。

 

CPOL = 1:SCK空闲时为高电平。

 

•CPHA:时钟相位

CPHA决定了数据是在时钟的哪个边沿被采样(读取)。

 

一个时钟周期,会有两个跳变沿,上升沿和下降沿。

ed181fe3dfbf231655f0fac302bc44.jpg

 

CPHA = 0:数据在时钟的第一个跳边沿(上升沿)到来时被采样。

e5b1b81657e73a9b3a313972ac2182.jpg

 

CPHA = 1:数据在时钟的第二个跳变沿(下降沿)到来时被采样。

71246e2631e44001c383edde5be8c6.jpg

 

 

将CPOL和CPHA进行组合,就产生了SPI的四种工作模式(Mode):

 

1.模式 0 (Mode 0): CPOL=0, CPHA=0

○SCK空闲时为低电平。

○数据在SCK的上升沿(从低到高)时被采样。

○SCK的下降沿(从高到低)用于发送方改变数据线上的数据。

7df81dfc1b97d80bd888f001d386bb.jpg

 

举个例子:时钟线平时趴在地上(低),通信开始,它第一次站起来(上升沿),接收方赶紧看数据线!然后它又趴下(下降沿),发送方趁机把下一个数据放数据线上准备好。

 

2.模式 1 (Mode 1): CPOL=0, CPHA=1

○SCK空闲时为低电平。

○SCK的上升沿(从低到高,这是时钟的第一个跳变沿)用于发送方改变数据线上的数据。

○数据在SCK的下降沿(从高到低,这是时钟从活动状态回到空闲状态的第二个跳变沿)被采样。

5b5f3ec4ce0c7fcda5325c390ed3ae.jpg

 

举个例子:时钟线平时趴在地上(低),通信开始,它站起来(上升沿),发送方把数据放好。然后它又趴下(下降沿),接收方赶紧看数据线!

 

3.模式 2 (Mode 2): CPOL=1, CPHA=0

○SCK空闲时为高电平。

○数据在SCK的下降沿(从高到低,这是时钟从空闲状态进入活动状态的第一个跳变)被采样。

○SCK的上升沿(从低到高,这是时钟的第二个跳变)用于发送方改变数据线上的数据。

9a9f59165fc520e1c1018f8484c2f4.jpg

举个例子:时钟线平时站着(高),通信开始,它第一次趴下(下降沿),接收方赶紧看数据线!然后它又站起来(上升沿),发送方趁机把下一个数据放数据线上准备好。

 

 

4.模式 3 (Mode 3): CPOL=1, CPHA=1

•SCK空闲时为高电平。

•SCK的下降沿(从高到低,这是时钟的第一个跳变)用于发送方改变数据线上的数据。

•数据在SCK的上升沿(从低到高,这是时钟从活动状态回到空闲状态的第二个跳变)被采样。

7b22adb1aeb73d859bb73874c2a7b1.jpg

举个例子:时钟线平时站着(高),通信开始,它趴下(下降沿),发送方把数据放好。然后它又站起来(上升沿),接收方赶紧看数据线!

 

理解上面这些图,面试再也不用慌啦,如果心理素质强的,直接现场边画边讲解效果更好。

 

为什么模式必须匹配?

 

因为SPI是同步通信,主从双方必须对数据的“节拍”达成一致。

 

主机的时钟波形、发送数据改变的时机、接收数据采样的时机,必须和从机期望的时钟波形、发送数据改变的时机、接收数据采样的时机完全对得上。

 

如果主机配置的是模式0(CPOL=0, CPHA=0),它会在时钟上升沿发出下一个脉冲并准备好数据,在下降沿改变数据线电平,并在上升沿采样数据。

 

如果从机配置的是模式3(CPOL=1, CPHA=1),它期望空闲时时钟是高电平(跟主机的低电平就不符),期望在时钟上升沿采样数据(跟主机的采样时机可能不符,取决于时钟波形)。

 

这种不匹配会导致:

•时钟信号的空闲电平就不对,从机可能根本不认为通信开始了。

•即使时钟勉强看起来像样,主机发送方在某个边沿改变数据电平,但从机接收方却在错误的边沿去采样,这时候数据线上的电平可能还在变化中,或者已经是下一个bit的电平了。结果自然是采样到错误的数据。

 

所以,当你的SPI通信出现问题时,第一件事就是去查从设备(传感器、屏幕、存储器等)的datasheet,找到它要求的SPI模式(CPOL和CPHA)。然后在你的单片机SPI配置寄存器里,把CPOL和CPHA位设置成对应的值。

 

对于常见的STM32、GD32、或其他厂家的单片机,SPI外设的控制寄存器里都会有专门的位来控制CPOL和CPHA。比如在某个单片机的SPI控制寄存器1 (SPI_CR1) 里,可能就有CPOL和CPHA这两个位。

 

比如要配置成模式0,你就把CPOL和CPHA都写0。

 

要配置成模式3,就把CPOL和CPHA都写1。

 

那对于一些用SPI的外围从机芯片呢?怎么看是用的SPI的哪种模式?

 

我们拿W25Q64这颗Flash芯片举例,我们在芯片数据手册上找到关于SPI的介绍。上面有写支持的模式,比如这颗芯片支持模式0(Mode 0)和模式3(Mode 3)。

f0adfb49fcc0b758fc575cd5c2b5a0.jpg

 

就是这么简单,但却是确保通信正常的前提。

 

当然,SPI还有其他一些需要注意的配置,比如数据长度(8位还是16位)、数据位序(MSB First还是LSB First)、时钟分频等。但就模式而言,CPOL和CPHA是核心中的核心。

 

把SPI的这套逻辑摸透了,你会发现,其实它没那么玄乎,无非就是信号的配合和时序的同步。搞懂了模式的区别,datasheet上的时序图看起来也不会那么陌生和可怕了。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表凡亿课堂立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。
相关阅读
进入分区查看更多精彩内容>
精彩评论

暂无评论