SPI 通信协议详解

article/2025/9/21 13:58:01

SPI通信协议详解

写在最前: 本文讲述了SPI通信协议的基本内容包括如下

  • SPI的基础知识
  • SPI的读写时序

本文重点参考 英文维基百科 中文维基百科 百度百科

注意: 倘若读者有足够的耐心和英文水平,强烈建议自行去英文维基百科去阅读相关知识。

相关链接:
SPI中文维基百科(没有翻译全)
SPI 英文维基百科


本文为原创文章


SPI 的基本内容

  首先来看SPI接口的组成,图片来自维基百科。基本的有4根线,分别是 SCKL即时钟线, MOSI主机master输出从机slave输入,即主机向从机输送数据,MISO主机输入,从机输出,即从机向主机发送数据。SS或者叫CS(分别是 slave select 和chip select)是一个东西,片选线,用来表示从机被选中,开始通信。

在这里插入图片描述

  在这里先解释一些东西。SPI可以接多个从机。其中SCLK MOSI MISO是所有设备共享的,但是 SS 不是共享的,每个从机都有一个SS。如下图:
在这里插入图片描述

   SS通常在电平被拉低时开始通信。如果在单主单从下,有些设备可以一直在低电平,保持与主机的通信,比如OLED我的OLED的CS脚直接悬空了也能保持通信。但有些设备不行,英文维基百科上有一个例子。如下:

If a single slave device is used, the SS pin may be fixed to logic low if the slave permits it. Some slaves require a falling edge of the chip select signal to initiate an action. An example is the Maxim MAX1242 ADC, which starts conversion on a high→low transition. With multiple slave devices, an independent SS signal is required from the master for each slave device.

该设备需要一个下降沿信号来表示 active 然后通信。
  然后我们再解释下 SCLK MOSI MISO。如果读者有接触过IIC协议,应该知道我们需要发送起始信号 应答信号等流程。但是SPI不一样,参考一些中文博客的说法,SPI是在进行数据交换。这个描述其实很贴切,稍后会详细解释。现在我们需要明白的是,不同于IIC读写分别有时序,SPI在每两个信号沿(即SCLK的一次完整地拉高拉低)过程中,主机向从机输送了一个bit地数据,从机也向主机输送了一个bit地数据,尽管有时候我们只想要写数据或者只想要读数据。不论是读还是写数据,时钟信号SCLK都由主机发出。

从宏观来看SPI通信的过程

  首先我们需要清楚,MOSI是主机向从机传输数据,MISO是从机向主机传输数据,而何时传输数据由SCLK地电平变化来表示,在ss被拉低后,设备开始通信,随着SCLK的一次拉高拉低,一位的数据便传输了。我们先宏观来看这个过程。图片来自百度百科:
在这里插入图片描述

  如果看的不是很明白,我来做一些解释。其中的脉冲其实就是SCLK的电平变化,上应该就是上升沿,下应该就是下降沿(大概?),主机sbuff就是主机准备发出去的数据,从机sbuff是从机发出的数据,sdi是MISO,sdo是MOSI。我们再仔细看看数据是如何交换的。在1上的时候,主机和从机分别移出了一位,把数据放到了sdisdo上,在1下的时候主机接受了MISO和从机接受了MOSI上的数据,并把数据作为自己的最低位(LSB)。我们再看看维基百科上如何说明这个过程,希望读者能认真看完这段英文,讲的真的很清楚。

Transmissions normally involve two shift registers of some given word-size, such as eight bits, one in the master and one in the slave; they are connected in a virtual ring topology. Data is usually shifted out with the most significant bit first. On the clock edge, both master and slave shift out a bit and output it on the transmission line to the counterpart. On the next clock edge, at each receiver the bit is sampled from the transmission line and set as a new least-significant bit of the shift register.After the register bits have been shifted out and in, the master and slave have exchanged register values. If more data needs to be exchanged, the shift registers are reloaded and the process repeats. Transmission may continue for any number of clock cycles. When complete, the master stops toggling the clock signal, and typically deselects the slave.
传输通常会使用到给定字长的两个移位寄存器,一个在主设备中,一个在从设备中; 它们以虚拟环形拓朴连接。 数据通常先移出最大的位。 在时钟边沿,主机和从机均移出一位,然后在传输线上输出给对方。 在下一个时钟沿,每个接收器都从传输线接受该位,并设置为移位寄存器的新的最低有效位。 在完成这样一个移出-移入的周期后,主机和从机就交换寄存器中的一位。 如果需要更多的数据交换,则需要重新加载移位寄存器并重复该过程。 传输可能会持续任意数量的时钟周期。 完成后,主设备会停止切换时钟信号,并通常会取消选择从设备。

再开始了解具体的时序

  希望读者能够通过上文能够了解SPI是如何工作的。但是仅仅知道这些还不足以写出对应的程序来模拟SPI。我们接下来需要了解更多的细节。

  我们从百度百科摘下来的图片可以看出在上升沿移出了数据,然后在下降沿接受了数据。但是其实并非一定要在上升沿移出数据并放到数据线上,下降沿接受数据到到寄存器里。
  我们首先来了解时钟极性时钟相位(Clock polarity and phase)。时钟极性通常写作CPOL(clock polarity),时钟相位通常写作CPHA(clock phase)。这两个参数有时可以自行配置,有时则是设备固定,这两个参数决定了我们的SPI到底如何通信。

注意:文中关键概念: 前沿(leading edge)、 后沿(trailing edge) 、上升沿(rising edge)、 下降沿(falling edge)、 捕获(captures) 、采样(sample)、 锁存(latch) 、改变(change)

  时钟极性CPOL表示在空闲时,SCLK是高电平还是低电平,如果SCLK配置为0,那么空闲时就是低电平,配置为1,那么空闲时就是高电平。最方便的记忆方法就是 0 就是低电平 ,1 就是高电平。

  时钟相位CPHA表示,在何时 捕获(capture)改变 数据。其中捕获有很多种说法,捕获(captures)采样(sample)锁存(latch)说的其实是一回事,在本文我们采用捕获这一说法。时钟极性很好解释,但是时钟相位就不那么容易解释了。首先需要知道 前沿后沿,现在我们结合起时钟极性CPOL来了解这个问题,然后再去了解时钟相位CPHA

  按照SPI协议通信的要求,首先是SS(CS)被拉低,然后开始通信。那么根据时钟极性,我们可以知道SS被拉低后,SCLK有两种可能,若CPOL=0,那么SCLK就是从0开始,若CPOL=1,那么就是从1开始。当主机改变SCLK时,数据交换就开始了。这里我们称 第一次发生的时钟改变叫做前沿(leading edge),随后在发生的时钟改变叫做后沿(trailing)(我并不是专业相关,只是根据我的理解给的定义),一个前沿再加一个后沿完成了一个时钟周期。现在我们通过一些思考来巩固这个内容。假如 CPOL=0,那么前沿就是一个上升沿后沿就是一个下降沿。假如CPOL=1,那么前沿就是一个下降沿后沿就是一个上升沿。

  看看维基百科的表述,仅摘录CPOL=0:

CPOL=0 is a clock which idles at 0, and each cycle consists of a pulse of 1. That is, the leading edge is a rising edge, and the trailing edge is a falling edge.

  有了这些知识铺垫,终于可以解释时钟相位CPHA了。可能有些难以理解,请仔细斟酌意思,以下是我自己总结的,稍后也会给出维基百科的定义,强烈推荐阅读。

  如果CPHA=0,那么前沿发生采样后沿发生数据的改变

  如果CPHA=1,那么后沿发生数据的改变前沿发生数据的采样

  所谓数据的采样,就是在之前宏观意义上的把数据接受到寄存器里,所谓数据的改变(不同文章有不同的叫法,有叫移出 输送的,但在笔者看来和改变是一个意思,笔者对移出输送的含义其实并不是很理解,在维基百科中,使用的是改变(change)) ,就是把数据从寄存器移出,并放置在MOSIMISO上。

现在我们来看维基百科对此的定义,下面这段话很重要,希望能耐心看完。

For CPHA=0, the “out” side changes the data on the trailing edge of the preceding clock cycle, while the “in” side captures the data on (or shortly after) the leading edge of the clock cycle. The out side holds the data valid until the trailing edge of the current clock cycle. For the first cycle, the first bit must be on the MOSI line before the leading clock edge.

An alternative way of considering it is to say that a CPHA=0 cycle consists of a half cycle with the clock idle, followed by a half cycle with the clock asserted.

For CPHA=1, the “out” side changes the data on the leading edge of the current clock cycle, while the “in” side captures the data on (or shortly after) the trailing edge of the clock cycle. The out side holds the data valid until the leading edge of the following clock cycle. For the last cycle, the slave holds the MISO line valid until slave select is deasserted.

An alternative way of considering it is to say that a CPHA=1 cycle consists of a half cycle with the clock asserted, followed by a half cycle with the clock idle.

看完这段话后我们需要一张图片,图片来自维基百科
在这里插入图片描述

  我们挑选一个 CPOL=1,CPHA=1的情况来举例说明。
对于CPOL=1,那么时钟前沿就是一个下降沿,后沿是一个上升沿。那么从维基百科的说明里看出,“out” side(对于MOSI来说out是主机,对于MISO来说,out是从机)在当前时钟周期的leading edge(结合CPOL,前沿就是下降沿)会改变数据,也就是把数据输送到 MOSI(主机输送)和MISO(从机输送)两根数据线上。 “in” side 捕获数据发生在后沿,结合CPOL,也就是上升沿,也有可能在上升沿之后(shortly after),以后你查看你设备SPI通信的要求时,你会看到一系列参数,比如信号的建立事件等,因为不是马上通信完成的。文中也指出"the out side holds the data valid until the leading edge of the following clock cycle." 也就是输送的信号需要保持稳定,直到下一个 leading edge(结合CPOL 就是下降沿)到来才能发生改变。那么通俗一点地解释,数据在上升沿后要保持稳定,直到下一个下降沿到来,那么说明我们主机和从机读取数据要在上升沿后,下降沿前。数据在下降沿发生改变(change),也就是我们在下降沿后设置好主机MOSI(不用考虑从机,从机发送数据是从机的事情,从机会自己在下降沿改变数据),然后到下一个上升沿,从机就会采样数据,同时你也可以读取从机发送过来的数据。

  用软件模拟SPI的流程图就出来了:

  手动拉低SCLK:主机去改变 MOSI 的电平表示即将发送的数据,从机自己设置MISO的电平表示发送给主机的数据。

  手动拉高SCLK:从机会采样即接收在MOSI的数据,如果主机需要读取,可以读取MISO上的数据

  如此循环。

如果感觉自己掌握了,那就再看一个CPOL=0,CPHA=0的例子,我们稍加思考,发现和CPOL=1,CPHA=1相像,都是在上升沿捕获数据,下降沿改变数据。事实上,这两种情况时最常见的情况,即上升沿捕获,下降沿改变。
百科可能有一些绕口," the “out” side changes the data on the trailing edge of the preceding clock cycle ",因为CPOL=0时,一个时钟就是上升沿马上就要捕获数据,第二个再是下降沿,因此用了"preceding clock cycle"这个说法,自己体会下。
以下是维基百科给出的代码,风格可能你见到过的不太一样,代码CPOL=0 CPHA=0

/** Simultaneously transmit and receive a byte on the SPI.** Polarity and phase are assumed to be both 0, i.e.:*   - input data is captured on rising edge of SCLK.*   - output data is propagated on falling edge of SCLK.** Returns the received byte.*/
uint8_t SPI_transfer_byte(uint8_t byte_out)
{uint8_t byte_in = 0;uint8_t bit;for (bit = 0x80; bit; bit >>= 1) {/* Shift-out a bit to the MOSI line */write_MOSI((byte_out & bit) ? HIGH : LOW);/* Delay for at least the peer's setup time */delay(SPI_SCLK_LOW_TIME);/* Pull the clock line high */write_SCLK(HIGH);/* Shift-in a bit from the MISO line */if (read_MISO() == HIGH)byte_in |= bit;/* Delay for at least the peer's hold time */delay(SPI_SCLK_HIGH_TIME);/* Pull the clock line low */write_SCLK(LOW);}return byte_in;
}

  这段代码我们看出来了其实数据并不是单向的读写,更像是一种交换,主机在输出,从机也在输出,有读也有写。
注意: 有读也有写意味着如果主机试图向从机读取数据(如向温度传感器),那么主机也必须发送数据。用代码举个例子:

// Send a dummy byte to receive the contents of the WHOAMI registerint whoami = SPI_transfer_byte(0x00);

SPI_transfer_byte函数就是上文代码里的函数。我们如果想要读取WHO_ AM _ I寄存器,那么也需要write一个字节的数据,称之为 dummy byte

SPI如何操纵设备

  讲解完了SPI的时序,那么就要思考实际应用中到底是如何使用的,一个设备里有好多的寄存器,如何才能对它进行读写呢?
   这个问题取决于你的设备,需要查阅你的芯片手册。我这里举个例子:
在这里插入图片描述

  这是一款能用SPI通信的陀螺仪,里面对SPI的介绍中,你可以看到:
  该设备在上升沿采样,下降沿输送,这里的说法是latch,在文中提到过,是一样的。没有看出是CPOL是0还是1,因为我没有截图完整,前面有一个时序图,可以看出CPOL其实是 1,这里就不截图了。
  该设备接收最高位,意味着我们需要先发送最高位(MSB),再发送(LSB)。部分读者可能会疑惑本文直接假定了先发送最高位,后最低位。事实上这是最常见的,也有例外(维基百科没有距离,但是说了通常先发送最高位)。而且带有硬件SPI的单片机通常都能配置寄存器选择先发送最高位还是最低位。
  操作方法是先发送 7位寄存器地址,其中最高位是读写位,0表示读,1表示写。

以上只是以我的设备举例,具体方法请查阅你的设备的datasheet


http://chatgpt.dhexx.cn/article/y4wYXC9c.shtml

相关文章

通信协议篇——SPI通信

通信协议篇——SPI通信 1.简介 SPI(Serial Peripheral Interface)是一种高速、同步、全双工串行通信总线,采用主从机通信模式,主要应用在EEPROM,FLASH,实时时钟,AD转换器等。 2.原理 通信方…

SPI接口通信协议详解:SPI时序、2线、3线、4线SPI及4种常用工作模式

简介 SPI通信原理比I2C要简单,它主要是主从方式通信。这种模式通常只有一个主机和一个或者多个从机,标准的SPI是4根线,分别是SSEL(片选,也写作 SCS)、SCLK(时钟,也写作SCK)、MOSI(主机输出从机输入Master Output/Slav…

详解UART、I2C、SPI常用通信协议(全是细节)

前言 UART、I2C和SPI是我们在嵌入式开发中比较常见的通信协议了,没有最好的通信协议,每个通信协议都有自己的优缺点。如果想要通信速度快,SPI 将是理想的选择;如果用户想要连接多个设备而不是过于复杂,I2C 将是理想的选…

【总线】SPI 通信协议

目录 SPI总线协议概述 串行与并行通信 SPI通信介绍 SPI的工作原理 时钟 从属选择 多个从机 常规方法 菊花链方法 MOSI 和 MISO SPI 数据传输的步骤 SPI 的优缺点 优点 缺点 文章参考 SPI总线协议概述 SPI是许多不同设备使用的通用通信协议。例如,SD卡…

SPI通信协议详解,一篇就够!

一、什么是SPI? SPI 的英文全称为 Serial Peripheral Interface,顾名思义为串行外设接口。SPI 是一种同步串行通信接口规范,主要应用于嵌入式系统中的短距离通信。该接口由摩托罗拉在20世纪80年代中期开发,后发展成了行业规范。 …

2021年游戏项目的十大编程语言:C++、Java、C#均上榜

在这个技术驱动的世界里,游戏行业是全球增长最快的行业之一。在每一款华丽精美的电子游戏背后,都有一种编程语言,为用户提供优质的体验。游戏开发者利用顶级的编程语言来构建游戏。不同的游戏项目使用了不同的编程语言,这取决于游…

2021 编程语言排行榜

点击“终码一生”,关注,置顶公众号 每日技术干货,第一时间送达! IEEE Spectrum 发布了 2021 年编程语言排行榜,官方的标题是:Python 在新技术领域依然是主导地位。 Python 近几年随着大数据、数据挖掘、人…

2020 年最牛逼的 10 门编程语言

先看再点赞,给自己一点思考的时间,微信搜索【沉默王二】关注这个有颜值却假装靠才华苟且的程序员。 本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题。 对于很多初学编程的人来说,尤其是马上要入…

世界上到底有多少种编程语言?

最近,网站上看到一个很有意思的问题:世界上到底有多少种编程语言? 查遍网络之后,仍然没有找到准确答案,只知道几千的数量是有的,但是我们常用的也就几十来个,其中最常见的便是Java、Python、C、…

世界上最难的5种编程语言

世界上最难的5种编程语言 每个程序员都熟悉许多编程语言。许多编程语言都是高级的,它们的语法是人类可读的。然而,也有一些低级语言,对于一个人来说,读起来很困难,但是可以理解。然而,您是否遇到过一种既不…

2018年最流行的十大编程语言,有你用的吗?

对于编程界的初学者来说,最大的困难是决定从何处入手,或者应掌握哪种语言才能在职场上平步青云。有时,专业程序员也面临学习一门新语言似乎更卓有成效的情形。 无论是什么原因,下面列出了世界上最流行的编程语言,以便了…

5月编程排行榜出炉,最佳编程语言是谁?

技术的发展日新月异,作为开发者,应该时刻关注这些变化,不断学习才能跟上时代步伐。 编程语言层出不穷,关于“ 最佳编程语言 ”的争论也从未停止,网友们各抒己见...... 网友A: 人生苦短,我选Pyt…

十大热门编程语言的介绍

小编给大家分享一篇关于现阶段十大热门编程语言的文章:经过流行的搜索引擎,如谷歌,必应,雅虎,维基百科,亚马逊,YouTube和百度,用于计算评级;得出十大热门编程语言排行榜的…

GitHub2022年十大热门编程语言榜单

全球知名代码托管平台 GitHub发布的2022年GitHub Octoverse年度报告公布了全球最流行的十大编程语言,其中JavaScript蝉联第一,Python位列次席。 编程是技术革新的核心,对于所有的编程开发人员来说,对世界范围内编程语言发展和趋势…

2021年十大热门编程语言

几乎可以肯定,每个人都知道,在当今数字先进的世界中,技术是如何快速变化的。经常通过定期更新和改进来观察替代技术之间的相互超越已成为一种正常现象。在这一切之中,一个领域因技术世界的如此多变的性质而受到很大的影响&#xf…

十大编程语言,每一个都不容易学,但每一个又很有用,黑客必备

一定要注意,您选择的编程将在很大程度上取决于您要定位的系统类型和计划使用的漏洞。因此,根据您的策略,任何语言都会很棒。 1. C语言 它被称为“所有编程语言之母”,也是Hacking社区中的关键语言。今天,我们拥有的大…

抖音照片图集怎么制作,如何将图片做成视频上传抖音?

抖音最近被很多人当做茶余饭后不可或缺的娱乐项目,丰富了很多人的业余生活,也成就了很多抖音人,经常在抖音上会看到很多不是直接拍摄的视频,而是通过图片图集的方式展示出来的视频,图片中还可以配上相应的文字&#xf…

手把手教你抖音怎么用图片做视频!

抖音是一款短视频APP,在抖音里人们可以上传视频,录制视频,看到别人的视频,抖音目前很受年轻人的欢迎,使用抖音的人高达几个亿;我们在抖音上看到的照片视频,其实大部分是在电脑制作后上传的一般比…

如何用照片做抖音视频?这样剪辑电子相册

如果只是在抖音中拍摄视频的话,相信这个操作大家都会吧?毕竟现如今的抖音可以说是全民在用了,关于如何拍摄视频发布到抖音,这个操作也几乎是人人都会的。但是拍摄视频你会,你又知道应该如何用照片来制作一个抖音视频吗…

[短视频运营] 抖音最新风口,漫改图文号,变现模式非常简单

这几天抖音出现了一个新的风口,千万不要错过,抖音召开了抖音创作者大会,在大会上有几件事的披露引起了广泛关注,对于每一个在抖音上的创作者来说都是重大的事件。 ​第一、抖音在大会上确定未来一年将会把更多的重点放在图文和中…