SPI协议(W25Q初遇)

512 阅读14分钟

1.SPI通信简介

  • SPI(serial peripheral interface)字面翻译是串行外设接口,是一种通用的数据总线,适用于主控和外挂芯片之间的通信,与IIC应用领域非常相似。

  • IIC无论是在硬件电路还是在软件时序设计的都是较为复杂的,硬件上需要配置成开漏外加上拉的模式,软件上需要一根数据线兼顾数据收发、应答位收发、寻址机制的设计等等,使得IIC的性价比极高,可以在消耗最低硬件资源的情况下实现最多的功能。在硬件上无论挂载多少个设备(128最多)都只需要两根通讯线,在软件上数据双向通信、应答位都可以实现。IIC既实现硬件上最少的通信线,又实现软件上最多的功能。

  • 但是IIC的缺点在于:IIC开漏外加上拉电阻的电路结构,使得通讯线高电平的驱动能力较弱,会导致通信线由低电平到高电平的时候上升沿会比较长,会最大限制IIC的通信速度,所以IIC的标准模式只有100KHz的时钟频率快速模式也只有400KHz,虽然后边改进电路设计出了高速模式可达3.4MHz,但是普及程度不高,一般情况下认为IIC时钟速度最高400KHz,相比SPI慢很多。

  • SPI有四根通信线,分别是SCK(serial CLOCK串行时钟线)、MOSI(master output slave input主机输出从机输入)、MISO(master input slave output主机输入从机输出)、SS(slave select从机选择)

  • 同步:同步通信是指发送和接收双方在同一时刻使用相同的时钟信号进行数据传输。

    • SCK引脚用于提供时钟信号,数据位的输出和输入都是在SCK的上升沿或下降沿进行,数据位的收发时刻因此得以确定。同步时序下时钟快慢或中途暂停都没问题。SCK相当于IIC通信下的SCL,作用相同。

2.硬件电路

这个图是SPI的一个典型电路,左边是SPI主机,主导整个SPI总线,一般是用控制器做主机如stm32,由于有3个从机,所以SS有3根,加上SCK、MOSI、MISO共6根,由于SPI所有通信线都是单端信号,高低电平都是相对于GND的电压差,单端信号所有的设备需要共地,图中未画出,但是必须要接。如果从机没有独立供电的情况下,主机需引出VCC给从机供电。

  • SCK时钟线完全由主机掌控,对主机来说时钟线为输出,对于所有主机来说时钟线都为输入,主机的同步时钟将送到各个从机。

  • 主机的SS线都是输出,从机的SS都是输入,SS线是低电平有效,主机在指定从机时只需将SS置低电平即可。主机初始化之后所有的SS都输出高电平,谁也不指定,当需要和从机1进行通信时就把SS1线输出低电平,此时主机在数据引脚进行的传输只有从机1会响应,当主机和从机1通信完成之后将会把SS1置回高电平,结束通信。

  • 输出引脚配置为推挽输出,因为推挽输出在高低电平均具有较强的驱动能力,这将是的SPI引脚信号的下降沿非常迅速,上升沿也非常迅速,不像IIC下降沿迅速上升沿缓慢。得益于推挽输出的驱动能力,SPI信号变化的快,能达到更高的传输速度(MHz级别)。(响应速度的快的原因之一)

  • IIC由于要实现半双工,经常需要切换输入输出,还要实现多主机的时钟同步和总线仲裁,这些功能都不允许IIC使用推挽输出,易造成电源短路。IIC选择了更多的功能,因此只能放弃更强的性能。

  • SPI的MISO引脚中主机一个是输入,三个从机都是输出,如果三个从机始终都是推挽输出将会导致冲突,因此SPI协议中有一个规定,当从机的SS引脚为高电平,即从机未被选中时,它的MISO引脚需切换为高组态(相当于引脚断开,不输出任何电平),以防止一条线有多个输出导致电平冲突,只有当SS为低电平时MISO才允许变为推挽输出。由于这个切换过程都在从机里进行,一般我们写的是主机的程序,主机的程序中也无需关心此问题。

3.移位示意图(核心)

发送同时接收

  电路的工作流程:首先规定波特率时钟的上升沿,所有移位寄存器向左移动一位,移出去的位放在引脚上;波特率时钟的下降沿时,引脚上的位采样输入到移位寄存器的最低位。

  假设主机有个数据1010 1010要发送到从机,同时从机有个数据0101 0101要发送到主机,那么可以先驱动时钟产生一个上升沿,这时所有的位将会向左移动一次,从最高位移出去的数据将会放在通信线上,实际上是放在了输出寄存器,MOSI数据是1,即MOSI的电平是高电平,MISO的数据是0,所以MISO的电平是低电平。第一个时钟沿就是把主机和从机中移位寄存器的最高位分别放到MOSI和MISO的通信线上,这是数据的输出的部分。

 之后时钟继续运行,上升沿之后下一个边沿就是下降沿,在下降沿时主机和从机内都会进行数据采样输入,也就是MOSI里的1会采样输入到从机里的最低位。

 在下一个上升沿进行同样的操作,移位输出,主机现在的最高位,也就是原始数据的次高位输出到MOSI从机现在的最高位输出到MISO,随后下降沿数据采样输入  第三个时钟开始 一直到第八个时钟都是一样的过程,最终八个时钟过后得到如下结果,原本主机的1010 1010跑道从机里边,原来从机里的0101 0101跑到了主机里,实现了主机和从机一个字节数据的交换。  以上就是SPI的运行过程,SPI的数据收发都是基于字节交换这个基本单元进行,当主机需要发送一个字节同时接收一个字节时,就可以执行字节交换的时序,主机要发送的数据跑到从机,主机要从从机接收的数据跑到主机,完成了发送同时接收的目的。

只发送不接收

如果想只发送不接收,仍然可以调用交换字节的时序,发送同时接收,不过不看接收到的数据即可;只接收不发送同理,调用交换字节的时序,发送同时接收,不过会随便发送一个数据,目的是为了将从机的数据置换过来即可,读取置换后的数据就相当于接收,随意发送的数据从机并不会进行读取,不过这个随便的数据并不是真的随便,会统一发送0x00或0xff去和从机换数据。

4.SPI时序基本单元

  • 起始条件SS从高电平切换到低电平,是左边的图,SS是低电平有效,SS从高变到低代表着选中了某一个从机,也是通信的开始
  • 终止条件SS从低电平切换到高电平,是右边的图,SS从低电平变到高电平,就是结束了从机的选中状态,通信结束。

**在从机的选中的整个过程中,SS要一直保持低电平。**


  • HAL库这个基本单元建立在上边的移位模型上。基本单元中在上升沿开始移位还是下降沿移位SPI并没有限制死,给予可配置的选择,以兼容更多的芯片。这里SPI有两个可以配置的位,分别是CPOL(Clock Polarity时钟极性),CPHA(Clock phase时钟相位,每一位可配置为1或0, 总共组合起来有模式0、1、2、3共四种模式,模式虽多但功能一样,模式1接近于上边的知识内容。

5.SPI的四种模式

image.png

  • 极性:极性低表示空闲状态为低电平,极性高相反

image.png

  • 相位第一边沿采集。叫做第一相位,反之相反

  • 总结

image.png

模式零(最常用)

  • 模式0的CPHA=0,在时序上的区别在于模式0的数据移出移入的时机,会提前半个时钟,也就是相位提前。第一个边沿移入数据,第二个边沿移出数据,但是数据是需要先移出才能移入的,所以SCK在第一个边沿之前就要提前移出数据,或者说是在第0个边沿移出第一个边沿移入

模式一

  • 时序的基本内容是交换一个字节,CPOL=0代表空闲状态时SCK为低电平(极性为低),在SS未被选中时SCK默认低电平;CPHA=1表示SCK第一个边沿移出数据第二个边沿移入数据。 时序图中SS从机选择,通信开始之前SS为高电平,通信过程中SS始终保持低电平,通信结束SS恢复高电平

  • 最下边的MISO主机输入从机输出,多个从机连在一起,如果同时开启输出会造成冲突,解决方法是在SS未被选中的状态下,从机的MISO引脚需关断输出,即配置为高阻态输出状态,如图位于中间电平的为高阻态,SS下降沿之后从机的MISO被允许开启输出,SS上升沿之后从机的MISO必须置回高阻态。

  • 移位传输:因为CPHA=1,SCK第一个边沿移出数据,图中可见SCK第一个触发沿是上升沿,主机和从机同时移出数据,主机通过MOSI移出最高位,此时MISO的电平就代表了主机要发送的数据B7,从机通过MOSI移出最高位,此时MISO表示从机要发送的数据B7。时钟运行,产生下降沿,此时主机和从机同时移入数据,即进行数据采样。主机移出的B7进入从机移位寄存器的最低位,从机移出的B7进入主机移位寄存器的最低位,当一个时钟脉冲产生完毕时一个数据传输完毕,后边的数据交换同理,直到最后一个下降沿,数据B0传输完成,主机和从机完成一个字节的数据交换,如果只想交换一个字节数据,接下来就可以将SS置高电平结束通信。

  • 在SS的上升沿MISO还可以再进行变化,将MOSI置默认的高电平or低电平,也可以不管,因为SPI没有规定MOSI的默认电平,MISO从机必须置回高阻态。如果此时主机的MISO位上拉输入的话,那MISO的引脚就是默认的高电平,如果主机的引脚为浮空输入,那MISO的引脚电平不确定。如果主机还想进行数据交换,则不必把SS置回高电平,直接重复交换一个字节的时序即可。

模式2(与模式0对比)

模式2与模式0的区别在于模式0的CPOL=0,模式2的CPOL=1,两者的波形就是SCK的极性取反,剩下的流程完全一致

模式3(与模式1对比)

模式1和模式3的区别,模式1的CPOL=0,模式3的CPOL=1,两者的波形区别在于SCK的极性取反,其他地方没区别。

5.SPI发送单字节时序(基于W25Q64的SPI)

SPI对字节流控的规定与IIC不同,IIC规定一般是有效数据流第一个字节是寄存器地址,之后依次是读写的数据,使用的是读写寄存器的模型。

  • 在SPI中通常使用的是指令码加读写数据的模型,在SPI起始后第一个交换发送给从机的数据一般叫做指令码在从机中一般会定义一个指令集,当需要发送指令时,可以在起始后的第一个字节发送指令集里边的数据,指导从机完成相应的功能,不同的指令有不同的数据个数,

    • 有的指令仅需一个指令码即可完成,比如W25Q64的写使能和失能的指令;
    • 有的指令后面需要跟读写的数据,比如W25Q64的写数据和读数据等。
  • 对于上边的时序图,功能是发送0x06,具体意思由芯片厂商自定义,在W25Q64里边代表的是写使能。使用SPI模式0,在空闲状态时SS为低电平电平,SCK为低电平,MOSI和MISO的默认电平没有严格规定。SS产生下降沿,时序开始。???在(下降沿)时刻MISO和MOSI开始交换数据,MOSI由于指令码最高位仍然是0,所以保持低电平不变;MISO从机暂无数据发送给主机,引脚电平无变化。当W25Q64不需要回传数据时,手册规定MISO仍然为高阻态,从机未开启输出。

  • stm32的MISO是上拉输入,所以MISO呈现的是高电平,之后SCK第一个上升沿进行数据采样,从机采样得到0,主机采样得到1;第二个时钟时,主机数据仍然是0,所以波形没变化;后边一位一位的发送接收,直到第七位才开始变化,主机发送数据1,下降沿将数据移出,主机将1移动到MOSI,MOSI变为高电平,图中为软件模拟的时序,有延迟,并没有紧贴SCK的下降沿,不过并不影响,只需在下一个SCK上升之前完成即可。SCK上升沿数据采样输入,在最后一位下降沿数据变化,MOSI变为0,上升沿数据采样,从机接收0。SCK低电平是变化的,高电平是读取的时期,时序SCK最后一个上升沿结束,一个字节交换完毕。

  •  写使能是单独的指令,不需要跟随指令,SPI只需要交换一个字节即可。在SCK下降沿之后,SS置回高电平结束通信。主机用0x06换来从机的0xff,但是实际上从机并没有输出,0xff是默认的高电平,并没有实际意义。

  •  整个时序的功能是发送指令,指令码是0x06,从机一比对事先定义好的指令集,发现0x06是写使能的指令,从机就会控制硬件写使能,完成一个指令从发送到执行的过程

接口定义

image.png

6.HAL库配置

image.png

image.png

代码书写
FLASH初识

image.png

  • 每个数据位只能由1改写为0,不能由0改写为1
  • 写入数据前必须先擦除,擦除后,所有数据位变为1
  • 写入的最小单元是页,擦除的最小单元是扇区
  • 扇区擦除后写使能会自动复位,所以进行下一次写操作时还要来一次写使能