上次我们学完了I2C的通信,这次我们学一下SPI的通信。I2C通信和SPI通信差不多,两个协议的设计目的都一样。都是为了实现主控芯片和各种外挂芯片之间的数据交流。有了数据交流的能力,我们主控芯片就可以挂载并操纵各式各样的外部芯片。
上次我们完成了I2C的通信协议,这次我们来完成SPI通信协议的学习。
第一部分:SPI协议基础
SPI(Serial Peripheral Interface)是一种高速、全双工、同步的串行通信总线协议。它通常用于微控制器与各种外围设备(如传感器、SD卡、Flash存储器、LCD屏等)进行通信。
SPI协议的核心是主从模式,通常有一个主设备(Master,通常是MCU)和一个或多个从设备(Slave)。
1. 信号线
一个标准的SPI总线使用4根信号线:
-
SCK (Serial Clock) : 时钟信号,由主设备产生并输出给从设备。用于同步数据传输。
-
MOSI (Master Out Slave In) : 主设备数据输出,从设备数据输入。主设备通过这条线向从设备发送数据。
-
MISO (Master In Slave Out) : 主设备数据输入,从设备数据输出。主设备通过这条线接收从设备发送的数据。
-
NSS (Slave Select) : 从设备选择信号,低电平有效。由主设备控制,用于选择要进行通信的特定从设备。每个从设备都需要一个独立的NSS线。
注意 :NSS有时也被称为 CS(Chip Select) 或 SS(Slave Select)。
2. 通信过程
-
初始化:主设备配置好SPI的时钟频率、极性和相位。
-
选择从设备:主设备将目标从机的NSS引脚拉低。
-
数据传输:
-
主设备在SCK时钟的驱动下,将数据一位一位地从MOSI线移出。
-
同时,从设备也在SCK时钟的驱动下,将数据一位一位地从MISO线移出。
-
这是一个全双工过程:数据在MOSI和MISO线上同时进行传输。每产生一个SCK时钟周期,就完成一位数据的发送和一位数据的接收。
-
-
取消选择:通信完成后,主设备将NSS引脚拉高。
3. 时钟极性与相位(CPOL与CPHA)- 关键概念!
这是SPI配置中最关键的部分,决定了时钟的空闲状态和数据的采样时刻。它们共同定义了4种SPI模式。
-
CPOL (Clock Polarity): 时钟极性
-
CPOL = 0 : SCK在空闲时为低电平。
-
CPOL = 1 : SCK在空闲时为高电平。
-
-
CPHA (Clock Phase): 时钟相位
-
CPHA = 0 : 数据在第一个时钟边沿(即SCK从空闲状态跳变) 被采样。
-
CPHA = 1 : 数据在第二个时钟边沿 被采样。
-
四种模式组合:
| 模式 | CPOL | CPHA | 空闲时SCK | 数据采样时刻 | 数据切换时刻 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 低电平 | 第一个边沿(上升沿) | 第二个边沿(下降沿) |
| 1 | 0 | 1 | 低电平 | 第二个边沿(下降沿) | 第一个边沿(上升沿) |
| 2 | 1 | 0 | 高电平 | 第一个边沿(下降沿) | 第二个边沿(上升沿) |
| 3 | 1 | 1 | 高电平 | 第二个边沿(上升沿) | 第一个边沿(下降沿) |
重要 :主设备和从设备必须使用相同的SPI模式才能正常通信。请务必查阅你所连接的外设数据手册,确定它要求使用哪种模式。
第二部分:STM32F103C8T6中的SPI
STM32F103C8T6内部集成了两个SPI外设:SPI1和SPI2。
-
SPI1 是高速SPI,位于APB2总线上(最高72MHz)。
-
SPI2 是普通SPI,位于APB1总线上(最高36MHz)。
1. 主要特性
-
全双工/半双工同步传输。
-
8位或16位数据帧格式。
-
主模式或从模式操作。
-
支持多主模式。
-
8个主模式波特率预分频器(fPCLK/2, /4, /8, /16, /32, /64, /128, /256)。
-
硬件CRC校验,用于可靠通信。
-
NSS信号可以由硬件管理(硬件从设备选择) 或软件管理(任意GPIO模拟)。在实际项目中,更常用的是软件控制一个GPIO来模拟NSS信号,因为更灵活。
2. 引脚分布
对于STM32F103C8T6(LQFP48封装):
-
SPI1
-
NSS: PA4, PA15
-
SCK: PA5, PB3
-
MISO: PA6, PB4
-
MOSI: PA7, PB5
-
注意:SPI1的引脚有些与JTAG调试端口复用,使用时需要注意重映射和配置。
-
-
SPI2
-
NSS: PB12
-
SCK: PB13
-
MISO: PB14
-
MOSI: PB15
-
3. 配置步骤(以库函数或HAL库为例)
使用STM32CubeMX或直接编程来配置SPI通常包括以下步骤:
-
使能时钟: 使能SPI外设和对应GPIO端口的时钟。
-
GPIO配置 : 将相关引脚配置为复用推挽输出(对于SCK, MOSI) 和浮空输入(对于MISO) 。将NSS引脚配置为推挽输出(如果使用软件NSS)。
-
SPI参数配置:
-
模式: 主模式(SPI_MODE_MASTER)或从模式。
-
方向和数据大小: 全双工,8位或16位。
-
时钟极性和相位(CPOL/CPHA): 根据从设备选择模式0,1,2或3。
-
NSS管理: 通常选择"软件NSS"。
-
波特率预分频器 : 设置SCK时钟频率。
fSCK = fPCLK / Prescaler。确保不超过从设备支持的最大频率。 -
数据顺序: 通常为MSB(最高位)先行。
-
-
使能SPI。
4. 数据收发流程
在STM32中,数据通信主要通过读写数据寄存器(DR) 来完成。
-
发送数据: 将数据写入DR寄存器。硬件会自动将数据加载到发送缓冲区,并通过MOSI线在SCK时钟驱动下移出。
-
接收数据: 当数据通过MISO线移入时,硬件会自动将其存入接收缓冲区。读取DR寄存器即可获得接收到的数据。
在编程中,我们通常通过检查状态寄存器(SR) 中的标志位来管理这个过程:
-
TXE (Transmit Buffer Empty): 为1时,表示发送缓冲区为空,可以写入新的待发送数据。
-
RXNE (Receive Buffer Not Empty): 为1时,表示接收缓冲区非空,有数据可以读取。
总结
在STM32F103C8T6中使用SPI,你需要:
-
理解SPI基本原理,特别是4种模式。
-
查阅从设备数据手册,确定其SPI模式和最大SCK频率。
-
正确配置STM32的SPI外设(模式、速率、数据格式等)。
-
正确配置GPIO引脚。
-
编写数据收发函数,通常结合NSS引脚的控制。
三.SPI通信简介
1.简介

SPI是一种有摩托罗拉公司开发的一种通用数据总线。
SCK串行时钟线,MOSI主机输出从机输入,MISO主机输入从机输出,SS从机选择。
有时候这些引脚会叫别的名字,比如SCK肯会叫SCLK,CLK,CK。MOSI和MISO可能会叫DO和DI。SS有的地方可能会叫NSS,CS。这些不同的名称都是一个意思,了解就行。
2.功能介绍
SCK引脚:用来提供时钟信号,因为我们的SPI是同步时序。数据的输入输出都是在SCK的上升沿,下降沿完成的。这样数据位的收发时刻,就可以明确的确定。并且同步时序,时钟快点,慢点,暂停一下,都是没有问题的,对照I2C总线,这个SCK就相当于SCL。
全双工协议:我们的SPI是全双工协议,就是数据发送和数据接受单独各占一条线。发送用发送的线路,接收用接受的线路,两者互不影响。所以这里的MOSI和MISO分别用于发送和接受的两条线路。MOSI线是主机输出从机输入,如果主机接在这条线上,那么就是MO主机输出,如果是从机接在这条线上,那么就是SI从机输入,MISO线是主机输入从机输出。这就是全双工通信的两跟数据线。这两个数据线加在一起,就相当于I2C总线的SDA。当然I2C是一根数据线,兼具发送和接受。是半双工,这里SPI是一根发送,一根接受,所以是全双工。
全双工的好处就是简单高效。输出线就一直输出,输入线就一直输入。数据流的方向没有改变,也不用担心发送和接受没有协调好从而冲突了。坏处就是多了一根线,会有通信资源的浪费。
支持总线挂在多设备,使用的是一主多从的模型,切记SPI只支持一主多从模型,不支持多主机。这一点SPI从功能上没有I2C强大。I2C实现一主多从的方式是,在起始条件后,主机必须发送一个字节进行寻址,用来指定要和哪个从机通信。所以I2C这里,要设计分配地址和寻址的问题。但是SPI有一个专门指定要和哪个从机进行通信。所以这条专门用来指定从机的通信线,就是我们的SS从机选择线,并且这个SS肯不止1条,SPI表示,我有几个从机,我就开几个SS。所有从机一人一根,需要控制哪个从机,就接入哪个从机控制线SS。
这就是SPI实现一主多从,指定从机的方式。好处就是方便,坏处就是得加线。SPI没有应答机制的设计,发送数据就发送,接受数据就接受,至于对面是不是存在,SPI是不管的。
3.硬件电路
我们来看一下SPI的硬件电路

左边这里是SPI的主机,主导整个SPI的总线,主机一般都是控制器来做,比如STM32。
下面这里从机1,2,3。就是挂载在主机上的从机设备了,比如存储器,显示屏,通信模块,传感器,等等。
左边SPI主机实际上印出来6跟通信线。因为有3个从机,所以SS线需要3根。再加SCK,MISO,MOSO一共6根。当然SPI所有的通信线都是单端信号,他们的高低电平都是相对于GND的电压差,所以单端信号,所有的设备都需要共地。如果从机没有独立电源的话,主机还需要再额外引出电源正极VCC,给从机供电。
首先SCK时钟线:时钟线完全由主机掌控。所以对于主机来说,时钟线为输出,对于所有从机来说,时钟线都为输入,这样主机的同步时钟,就能送到各个从机了。
MOSI:主机输出,从机输入,主机通过MOSI进行输出,从机通过MOSI进行输入。
MISO:主机输入,从机输出,主机通过MISO进行输入,从机通过MISO进行输出。
每条线的传输方向都用箭头标记出来了。
接着是从机的选择问题,为了确定通信的目标,主机就需要另外引出多条SS控制线。分别接到各个从机的控制引脚,下面如果有三个从机,我们就需要引出三个SS从机选择线,分别接在各个从机的SS输入端。主机的SS都是输出,从机的SS都是输入,SS线都是低电平有效的,主机想指定谁,就把对应的SS线给拉低就可以了。
比如主机初始化之后,就把所有的SS线置高电平,谁也先不指定。要和哪个从机通信,就把哪个从机的SS置低电平,然后主机再数据引脚进行的传输,就只有这个从机能响应,其他从机的SS线是高电平,都会保持沉默。当主机和从机1通信完成后,就会把SS1置为高电平,这样从机1就知道,主机结束了和我的通信。从机2的话以此类推。
4.与I2C对比
当然同一时间主机只能和一个从机进行通信,如果主机同一时刻选择多个从机,就会导致数据冲突,这就是SPI选择从机的方式。不需要像I2C一样进行寻址。
输出引脚配置为推挽输出,输入引脚配置为浮空/上拉输入。
推挽是输出的话,高低电平都有很强的驱动能力,这将使得SPI引脚的下降沿,非常迅速,上升沿也非常迅速。不像I2C下降沿迅速,但是上升沿就缓慢了。那么得益于推挽输出的驱动能力,SPI信号鲜花的快,那么自然能达到更高的传输速度。一般SPI的信号都能轻松达到MHz速度级别。
这里I2C并不是不想使用更快的推挽输出,而是I2C需要切换半双工经常要切换输入输出,而且I2C又要实现多主机的时钟同步和总线仲裁,这些功能都不允许I2C使用推挽输出。要不然一不小心就电源短路了。所以I2C选择了更多的功能,自然就要放弃更强的性能了。
对于SPI来说,首先SPI不支持多主机,然后SPI又是全双工,SPI的输出引脚始终是输出,输入引脚始终是输入,基本不会出现冲突,所以SPI可以大胆的使用推挽输出。
不过当然SPI还是有一个冲突点的,就是MISO引脚

在这个引脚上可以看到,主机一个是输入,其他三个是从机都是输出,如果三个从机都是推挽输出的话,势必会导致冲突,所以再SPI协议里有一条规定,当从机的SS引脚为高电平,也就是从机为未被选中时,他的MISO引脚必须变为高阻态状态,高阻态就相当于引脚断开,不输入任何电平。这样就可以防止一条线有多个输出,而导致电平冲突的问题了,再SS为低电平时MISO才允许变为推挽输出,这就是SPI对这个可能的冲突做的规定。当然切换过程都是再从机里,我们一般写主机的程序。所以主机程序中,并不需要关注这个问题。
5.移位示意图

SPI的基本收发电路,就是使用了这样的一个移位模型。左边是SPI的主机,里面有一个八位的,右边是SPI从机,里面也有一个八位的移位寄存器。这里移位寄存器有一个时钟输入端,因为SPI一般是高位先行的,所以每来一个时钟,移位寄存器都会像左移位。移位寄存器的时钟源是由主机提供的。这里叫做波特率发生器,它产生时钟,驱动主机的移位寄存器进行移位。同时这个时钟也通过SCK引脚进行输出,接到从机的移位寄存器里,之后上面移位寄存器的接发是,主机移位寄存器移回去的数据通过MOSI引脚,接到从机移位寄存器的右边,从机移位寄存器左边移出去的数据,通过MISO引脚,输入到主机移位寄存器的右边。
工作流程:

首先我们规定波特率发生器时钟的上升沿,所有移位寄存器向左移动一位,移出去的位放在引脚上,波特率发生器时钟的下降沿,引脚上的位采样输入到移位寄器的最低位。假设主机有一个数据1010 1010要发送到从机,同时从机有个数据0101 0101要发送到主机那我们就可以驱动时钟,产生一个上升沿,这样所有的位就会往左移动一次

从做高位移出去的数据就会放在通信线上,实际上是放到了输出数据寄存器。此时MOSI数据是1那么MOSI的电平就是高电平,反之MISO电平就是低电平。
之后时钟继续运行,上升沿之后,下一个下降沿就是下降沿,再下降沿,主机和从机内都会对数据进行采样输入,也就是MOSI的1会采样输入到从机的最低位,MISO的0也会采集到主机的最低位


第二个时钟上升沿到来重复操作。

第二个时钟下降沿到来,对数据进行采样输入,以此类推。

最终八个时钟之后,数据完成转移。这就实现了主机和从机的一个字节的数据交换。
当主机发送一个字节,并且从机接受一个字节时候,就可以执行一下字节交换的时序。
如果只想发送,不想接受的话,其实很简单,我们依然调用接受字节的数据,发送同时接受,只是这个接受到的数据,我们不看他就行了。
如果只想接受不想发送的话,我们依然调用接受字节的数据,发送同时接受,只是我们会随便发送一个数据,只要能把从机的数据交换过来就可以了。我们读取置换过来的数据,不就是接受了吗,这里我们随便发送过去的数据,从机也不看她,当然这个随便的数据,我们不会真的随便发送,一般再接受的时候,我们会统一发送0x00或0xFF,去跟从机换数据,以上就是SPI的基本原理。
总结一下就是SPI的基础是交换一个字节,有了交换一个字节,就可以实现接受一个字节,发送一个字节,和发送同时接受一个字节这三个功能。所以可以看出,SPI在只执行发送和只执行接受的时候,会出现资源浪费的现象。不过全双工的通信,本来就会有浪费的现象发生。SPI表示我不在乎。
四.SPI时序基本单元
1.起始条件or终止条件

起始条件是SS从高电平切换到低电平,左边的图。SS是低电平有效的。终止条件是SS从低电平变为高电平,右边的图,就是结束了从机的选中状态。在从机整个选择状态中SS要始终保持为低电平。
2.交换一个字节(模式1)
这里改怎么移位,什么时候移位SPI并没有固定死,给了我们更多的选择,去兼容其他芯片。
在这里SPI有两个可以配置的位,CPOL:时钟极性,CPHA:时钟相位。每一位可以配置为1/0。总共组合起来就有模式0,模式1,模式2,模式3,这四种模式。
虽然模式很多,但是功能都是一样的,所以我们掌握其中一个就可以。

这个跟我们刚刚了解的是对应的。下面可以看到在SS未被选中时候,SCK是低电平。然后CPHA=1,表示SCK第一个边沿移出数据,第二个边沿移入数据。
可以看到原理图,在从机未通信时候始终为高电平,在从机通讯的时候为低电平。通信结束SS恢复为高电平。MISO是主机输入从机输出

因为有多个从机连接在了一起,如果同时开启输出会造成冲突,所以我们解决方法是,在SS未被选中的状态,从机的MISO必须关断输出,呈现高阻态的状态。

在这里SS高电平期间MISO用一根中间的线,表示高阻态。SS下降沿之后从机的MISO被允许开启输出,SS上升沿时候,从机的MISO必须呈现高阻态。
因为CPHA=1,SCK第一个边沿移出数据,这里可以看出,SCK第一个边沿是上升沿,主机和从机同时移出数据。主机通过MOSI移出最高位,从机通过MISO移除最高位,此时MOSI的电平,就代表着主机要发送的数据B7,从机通过MISO移出最高位,此时MISO表示从机要发送的数据B7。然后始终运行产生下降沿,此时主机和从机同时移入数据,也就是进行数据采样,这里主机移出的B7,进入从机移位寄存器的最低位,从机移出的B7进入主机移位寄存器的最低位。这样一个时钟脉冲产生完毕,一个数据位传输完毕。
接下来就是重复之前的过程,第二个脉冲过来,上升沿,主机和从机同时进行输出当前移位寄存器的最高位,第二次的最高位就是原始数据的B6,然后下降沿主机和从机移入数据,B6传输完成。之后继续重复以上操作,直到交换完成B0,此时主机和从机,就完成了一个字节的数据交换。
如果主机只想要交换一个字节,那么这时就可以置SS为高电平,结束通讯了。在SS的上升沿,MOSI还可以在变化一次,将MOSI置到一个默认的高电平或低电平,也可以不用管,因为SPI没有硬性规定MOSI默认的电平。然后MISO从机必须默认置为高阻态。
此时如果主机的MOSI为上拉输入的话那么MOSI引脚的电平为高电平。如果主机MISO为浮空输入,那么MISO引脚电平不确定,这是交换一个字节就结束的流程。
如果主机还想交换字节,那么主机就不必把SS置会高电平了。直接重复一下,交换一个字节的顺序。这就是传输多个字节的方法。
3.交换一个字节(模式0)重点

模式0和模式1的区别就是,模式0的CPHA=0,模式1的CPHA=1,就是模式0的数据移入和移出的时机会提前半个时钟。
模式0在第一个边沿就要移入数据,但是数据得先移出在移入对吧。所以在模式0的配置下,SCK在第一个边沿之前,就要提前开始移出数据了。或者把它称作在第0个边沿1移出,在第一个边沿移入。
时序:首先SS在下降沿开始通信,现在SCK还没有变化,但是SCK一旦开始变化,就要移入数据了所以此时趁SCK还没有变化,就要立刻触发移位输出,所以这里MOSI和MISO的输出是对齐SS的下降沿的,或者说这里把SS的下降沿也当作了时钟的一部分了。那么SS的下降沿触发了输出SCK上升沿,就可以采样输入数据了。这样B7就传输完毕,之后下降沿移出B6,在之后的上升沿移入B6。最终在第八个上升沿时,移入完成,整个字节交换完成。
之后SCA还有一个下降沿,如果主机需要交换一个字节的数据,那么在这个下降沿时MOSI置默认电平,不用处理,MISO也会变化一次这一位实际上是下一个字节的B7,因为相位提前了,所以下一位的B7回露个头,如果不需要的话SS上升沿之后,从机MISO必须置回高阻态。
如果想要连续交换数据,那么在最后一个下降沿主机放下一个字节的B7,从机也放下一个字节的B7,SCK上升沿正好接着采样第二个字节的B7。这样时序才拼接的上。
模式0和模式1的区别就是,模式0把数据变化的时机提前了,在实际应用中,模式0的应用是最多的。我们重点掌握模式0即可。
4.交换一个字节(模式2)
模式0和模式2的区别就是,模式0的CPOL=0,模式2的CPOL=1。就是SCK的波形取反一下。

5.交换一个字节(模式3)
模式3和模式1的区别就是,模式1的CPOL=0,模式3的CPOL=1。两者的波形也是SCK取反。

最后提醒一下,这个CPHA表示的是时钟的相位,决定是第一个时钟采样移入,还是第二个时钟采样移入,并不是规定上升沿采样,还是下降沿采样。当然在CPOL确定的情况下,CPHA确实回改变采样时刻的上升沿和下降沿。
比如,模式0的时候是SCK上升沿采样移入,模式1时候是SCK下降沿采样移入。
CPHA决定是第几个边沿采样,并不能单独决定是上升沿还是下降沿。
这四种模式,模式0和模式3都是上升沿采样,模式1和模式2都是下降沿采样。
五.完整的SPI波形
1.了解
因为每个芯片对SPI时序字节流功能的定义不一样,在这里就以W25Q64这个芯片进行演示。
SPI对字节流的规定,不像I2C那样。I2C的规定是有效字节流第一字节是寄存器地址,之后依次是读写的数据。使用的是读写寄存器的模型。而在SPI中通常采用的是指令码+读写数据的模型。
这个过程就是SPI在起始之后第一个交换发送给从机的数据,一般叫做指令码,在从机中对应的会定义一个指令集,当我们需要发送什么指令时,就可以在起始后第一个字节,发送指令集里面的数据,这样就能指导从机完成相应的功能了。
不同的指令,可以有不同的数据个数,有的指令只需要一个字节的指令码就可以完成,有的指令后面就需要在根要读写的数据。写数据指令后面就得跟上,我要在哪里写,我要写什么,读数据同理,后面就得跟上,要在哪里读,要读什么。这就是指令码+读写数据的模型。
在SPI的从机手册里,都会定义好指令集,什么指令对应什么功能。什么指令后面需要跟随什么数据,这些我们看芯片时候在仔细分析。
2.发送指令


首先是SPI发送指令,这个时序的功能是,向SS指定设备,发送指令0x06,指令0x06是什么意思呢,可以由芯片厂商自己规定,在W25Q64里面,这个芯片代表着写使能。
这里使用的是模式0,在这里空闲状态时,SS为高电平,SCK为低电平,MOSI和MISO默认电平没有严格规定。然后SS产生下降沿时序开始,MOSI和MISO就要开始变化数据了。
MOSI由于指令码最高位,仍然是0所以这里保持不变,MISO从机现在没有数据发给主机,引脚电平没有变化,实际上W25Q64不需要回传数据时,手册里规定的是MISO仍然是高阻态从机并没有开启输出,不过这也没问题,反这个数据我们不需要看。因为STM32的MISO是上拉输入,所以我们也不需要看。
之后SCK第一个上升沿进行数据采样,从机采样输入得到0,主机采样输入得到1。之后主机数据仍然是0,从机仍然是1。这样一位一位的发送接收。

直到这里,主机要发送1,下降沿数字移出,主机将1移出到MOSI,MOSI变为高电平,因为是软件模拟MISO没用紧贴着SCK下降沿,不过不慌,只需要在下一个SCK上升沿之前完成变化就行了。然后SCK上升沿,数据采样输入,下降沿数据采样,变为0.SCK低电平是变化的时机,高电平是读取的时机,这一块和I2C很像。
因为写使能是单独数据,是不需要跟随数据,SPI只需要交换一个字节就完成了。所以在SCK下降沿之后,置会高电平,通信结束。统计一下交换的电平就是,主机用0x06,换来了从机的0xFF。当然实际上,从机并没有输出,这个0xFF是默认的高电平。
从机会对比主机发送的指令集,发现是写使能,那么从机就会执行这条。
3.指定地址写
因为我们W25Q64有8M字节的存储空间,一个字节的8位地址肯定不够,分三个字节传输
-
1个字节 = 8位 -> 最大寻址范围 256 字节,远远不够。
-
2个字节 = 16位 -> 最大寻址范围 64KB (65,536 字节),还是不够。
-
3个字节 = 24位 -> 最大寻址范围 16MB (16,777,216 字节)。


第一个时钟完成,我们用0x02换来了0xFF,其中发送的0x02是一条指令,代表着写入一个数据的时序

因为我们还需要交换数据,所以在这个下降沿,下一个字节的最高位,放到MOSI上,之后同样的流程,交换一个字节,我们用0x12换来了0xFF。
根据W25Q64规定,写指令之后的字节,定义为地址的高位,所以这个0x12就表示发送地址的23-16位。之后发送一个字节0x34,就表示发送地址的15-8位,最后还是交换字节发送的是0x56,就表示发送地址的7-0位。
通过三个字节的交换,24位地址就发送完成了。
地址发送完成后,继续发送要写入的数据。这里波形是0x55,综合起来就是我要在0x123456地址下写入0x55这个数据。最后如果只写入数据的话,就可以结束了。
也可以继续发送数据,SPI里面也会有和I2C一样的地址指针,每读写一个字节,地址指针+1。就会依次写入到后续的连续空间里。
由于SPI没用应答机制,所以交换一个字节后,继续交换就可以了。
4.指定地址读


和上面一样,主机发送指令,读取数据,之后依次交换三个字节,,0x12,0x34,0x56.组合在一起就是0x123245,代表24位地址,

最后因为我们是读取数据,读取地址后我们就要开始接收数据,我们随便给从机一个数据,一般给0xFF就可以了。从机就会把0x123456地址下的数据,通过MISO发给主机。如果继续的话,从机内部地址指针+1,会连续读取从这个地址开始之后的地址数据。
最后数据传输完毕SS置会高电平数据传输结束。由于MISO是硬件控制的波形,所以他的数据变化都可以紧贴时钟的下降沿,另外可以看到MISO的最高位,实际上是在上一个字节最后一个下降沿提前发生的,因为我们用的是模式0,会提前半个周期。