SPI通信协议--在STM32中介绍(学习笔记)

上次我们学完了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. 通信过程

  1. 初始化:主设备配置好SPI的时钟频率、极性和相位。

  2. 选择从设备:主设备将目标从机的NSS引脚拉低。

  3. 数据传输

    • 主设备在SCK时钟的驱动下,将数据一位一位地从MOSI线移出。

    • 同时,从设备也在SCK时钟的驱动下,将数据一位一位地从MISO线移出。

    • 这是一个全双工过程:数据在MOSI和MISO线上同时进行传输。每产生一个SCK时钟周期,就完成一位数据的发送和一位数据的接收。

  4. 取消选择:通信完成后,主设备将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通常包括以下步骤:

  1. 使能时钟: 使能SPI外设和对应GPIO端口的时钟。

  2. GPIO配置 : 将相关引脚配置为复用推挽输出(对于SCK, MOSI)浮空输入(对于MISO) 。将NSS引脚配置为推挽输出(如果使用软件NSS)。

  3. SPI参数配置

    • 模式: 主模式(SPI_MODE_MASTER)或从模式。

    • 方向和数据大小: 全双工,8位或16位。

    • 时钟极性和相位(CPOL/CPHA): 根据从设备选择模式0,1,2或3。

    • NSS管理: 通常选择"软件NSS"。

    • 波特率预分频器 : 设置SCK时钟频率。fSCK = fPCLK / Prescaler。确保不超过从设备支持的最大频率。

    • 数据顺序: 通常为MSB(最高位)先行。

  4. 使能SPI

4. 数据收发流程

在STM32中,数据通信主要通过读写数据寄存器(DR) 来完成。

  • 发送数据: 将数据写入DR寄存器。硬件会自动将数据加载到发送缓冲区,并通过MOSI线在SCK时钟驱动下移出。

  • 接收数据: 当数据通过MISO线移入时,硬件会自动将其存入接收缓冲区。读取DR寄存器即可获得接收到的数据。

在编程中,我们通常通过检查状态寄存器(SR) 中的标志位来管理这个过程:

  • TXE (Transmit Buffer Empty): 为1时,表示发送缓冲区为空,可以写入新的待发送数据。

  • RXNE (Receive Buffer Not Empty): 为1时,表示接收缓冲区非空,有数据可以读取。

总结

在STM32F103C8T6中使用SPI,你需要:

  1. 理解SPI基本原理,特别是4种模式。

  2. 查阅从设备数据手册,确定其SPI模式和最大SCK频率。

  3. 正确配置STM32的SPI外设(模式、速率、数据格式等)。

  4. 正确配置GPIO引脚

  5. 编写数据收发函数,通常结合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,会提前半个周期。

相关推荐
愚昧之山绝望之谷开悟之坡1 小时前
业务接待-公务接待-商务接待
笔记
断水客1 小时前
如何在手机上搭建Linux学习环境
linux·运维·学习
电子科技圈2 小时前
IAR与Quintauris携手推进RISC-V汽车实时应用的功能安全软件开发
嵌入式硬件·安全·设计模式·编辑器·汽车·risc-v
j***12153 小时前
网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。
爬虫·学习·selenium
up向上up3 小时前
基于STM32的电子钟万年历Proteus仿真设计_LCD1602显示
stm32·单片机·proteus
大数据追光猿3 小时前
LangChain / LangGraph / AutoGPT / CrewAI / AutoGen 五大框架对比
经验分享·笔记·python·langchain·agent
q***07143 小时前
SocketTool、串口调试助手、MQTT中间件基础
单片机·嵌入式硬件·中间件
新晨单片机设计3 小时前
【S001A】基于STM32单片机视力保护仪【Proteus仿真+Keil程序+报告+原理图】
stm32·单片机·proteus
✎ ﹏梦醒͜ღ҉繁华落℘4 小时前
freeRTOS学习笔记(十四)--内存
笔记·学习