首页 > 其他分享 >SPI 通信协议详解

SPI 通信协议详解

时间:2024-08-17 14:23:55浏览次数:7  
标签:字节 主机 通信协议 SPI 从机 详解 边沿 数据

目录


一、概述

SPI(Serial Peripheral interface,串行外围设备接口) 通信协议是 Motorola 公司首先在其MC68HCXX 系列处理器上定义的。SPI 接口是一种高速的全双工同步的通信总线,已经广泛应用在众多 MCU、存储芯片、AD 转换器和 LCD 之间。

SPI 连成的串行总线是一种三线同步总线,总线上可以连接多个可作为主机的 MCU,装有 SPI 接口的输出设备,输入设备如液晶驱动、A/D 转换等外设,也可以简单连接到单个 TTL 移位寄存器的芯片。总线上允许连接多个能作主机的设备,但在任一瞬间只允许有一
个设备作为主机。总线的时钟线 SCK 由主机控制,另外两根分别是:主机输入/从机输出线 MISO主机输出/从机输入线 MOSI。下图就是 SPI 总线的典型结构图:

系统可以简单,也可以复杂,主要有以下几种形式:

  1. 一台主机 MCU 和若干台从机 MCU。
  2. 多台 MCU 互相连接成一个多主机系统。
  3. 一台主机 MCU 和若干台从机外围设备。

二、SPI 详解

1、基本信息

1.1 SPI 的引脚信息

  • MISOMaster In / Slave Out)主设备数据输入,从设备数据输出。
  • MOSIMaster Out / Slave In)主设备数据输出,从设备数据输入。
  • SCLKSerial Clock)时钟信号,由主设备产生。
  • CSChip Select)从设备片选信号,由主设备产生。

其他制造商可能会遵循其他命名规则,但是最终他们指的相同的含义。以下是一些常用术语,

  • MISO 也可以是 SIMODOUTDOSDOSO(在主机端);
  • MOSI 也可以是 SOMIDINDISDISI(在主机端);
  • CS 也可以是 CENSSSSEL
  • SCLK 也可以是 SCK

1.2 SPI 的工作原理

在主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。串行移位寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过 MISO 信号线返回给主机。这样,两个移位寄存器中的内容就被交换。外设的写操作和读操作是同步完成的。如果只是进行写操作,主机只需忽略接收到的字节。反之,若主机要读取从机的一个字节,就必须发送一个空字节引发从机传输。

1.3 SPI 的传输方式

SPI 总线具有三种传输方式:全双工、单工以及半双工传输方式。

有关这三种传输方式在 UART 通信协议详解 中已经介绍过,这里不再赘述。

2、SPI 的工作原理

在主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。串行移位寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过 MISO 信号线返回给主机。这样,两个移位寄存器中的内容就被交换(高位先行)。外设的写操作和读操作是同步完成的。如果只是进行写操作,主机只需忽略接收到的字节。反之,若主机要读取从机的一个字节,就必须发送一个空字节引发从机传输。

假设主机有个数据 10101010 10101010 10101010 要发送给从机,同时从机也有个数据 01010101 01010101 01010101 要发送到主机,

  1. 首先驱动时钟,先产生一个上升沿,这时,所有的位,会往左移动一次,从最高位移出去的数据,就会放到通信线上,数据放到通信线上(实际上是放到了输出数据寄存器),此时 MOSI 数据是 1,所以 MOSI 的电平就是高电平;而 MISO 的数据是 0,所以 MISO 的电平就是低电平,这就是第一个时钟上升沿执行的结果。
  2. 然后把主机和从机中移位寄存器的最高位分别放到 MOSIMISO 的通信线上,这就是数据的输出。
  3. 之后时钟继续运行,上升沿之后,下一个边沿就是下降沿,在下降沿时主机和从机内,都会进行数据采样输入,也就是,MOSI 的 1,会采样输入到从机这里的最低位;MISO 的 0,会采样输入到主机这里的最低位,这就是第一个时钟结束后的现象。
  4. 时钟继续运行,下一个上升沿,同样操作,移位输出,主机现在的最高位,也就是原始数据的最高位,输出到 MOSI,从机现在的最高位,输出到 MISO,变成主机的最低位…
  5. 八个时钟后,原来主机的 10101010,跑到从机里,而原来从机的 01010101跑到主机里了。

这样就实现了主机和从机一个字节的数据交换,SPI 的数据收发都是基于字节交换这个基本单元来实现的,当主机需要发送一个字节同时需要接受一个字节时,就可以执行一下字节交换的时序,这样主机要发送的数据跑到从机,主机要从从机接收的部分,跑到主机,这就完成发送同时接收的目的。如果只想发送不想接收,和原来一样,只是这次接收到的数据不看它就行了,只想接受不想发送就随便发一个数据只要能把从机的数据置换过来就行了,读取置换过来的数据,这里随便发过去的数据从机不会去看它,一般在接受的时候,统一发 0x00 或 0xFF,去跟从机交换数据。

3、SPI 的工作模式

3.1 SPI 时序基本单元

起始条件:SS 从高电平切换到低电平
终止条件:SS 从低电平切换到高电平
因此,在从机的整个选中状态中,SS 要始终保持为低电平。

3.2 CPOL 和 CPHA

SPI 通信协议具备 4 种工作模式,在讲这 4 种工作模式前,先介绍一下 CPOLCPHA

CPOLClock Polarity,时钟极性),当主从机没有数据传输的时候即空闲状态,SCL 线的电平状态。假如空闲状态是高电平,
CPOL=1;若空闲状态时低电平,那么 CPOL = 0

CPHAClock Phase,时钟相位)。实质指的是数据的采样时刻,CPHA = 0 的情况就表示数据的采样是从第 1 个边沿信号上即奇数边沿,具体是上升沿还是下降沿的问题,是由 CPOL 决定的。这里就存在一个问题:当开始传输第一个 bit 的时候,第 1 个时钟边沿就采集该数据了,那数据是什么时候输出来的呢?那么就有两种情况:

  • 一是 CS 使能的边沿
  • 二是上一帧数据的最后一个时钟沿

CPHA=1 的情况就是表示数据采样是从第 2 个边沿即偶数边沿,它的边沿极性要注意一点,不是和上面 CPHA=0 一样的边沿情况。前面的是奇数边沿采样数据,从 SCL 空闲状态的直接跳变,空闲状态是高电平,那么它就是下降沿,反之就是上升沿。由于 CPHA=1 是偶数边沿采样,所以需要根据偶数边沿判断,假如第一个边沿即奇数边沿是下降沿,那么偶数边沿的边沿极性就是上升沿。

同步通信时,数据的变化和采样都是在时钟边沿上进行的,每一个时钟周期都会有上升沿和下降沿两个边沿,那么数据的变化和采样就分别安排在两个不同的边沿,由于数据在产生和到它稳定是需要一定的时间,那么假如我们在第 1 个边沿信号把数据输出了,从机只能从第 2 个边沿信号去采样这个数据。

3.3 四种工作模式

由于 CPOLCPHA 都有两种不同状态,所以 SPI 分成了4 种模式。我们在开发的时候,使用比较多的是模式 0 和模式 3。见下表 SPI 工作模式表:

SPI 工作模式CPOLCPHASCL 空闲状态采样边沿采样时刻
000低电平上升沿奇数边沿
101低电平下降沿偶数边沿
210高电平下降沿奇数边沿
311高电平上升沿偶数边沿

下面分别对 SPI 的四种工作模式进行分析:

3.3.1 工作模式 0

  • CPOL=0:空闲状态时,SCK 为低电平。
  • CPHA=0:SCK 第一个边沿移入数据,第二个边沿移出数据。

MOSI 和 MISO 数据的有效信号需要在 SCK 奇数边沿保持稳定且被采样,在非采样时刻,MOSI 和 MISO 的有效信号才发生变化。

3.3.2 工作模式 1

  • CPOL=0:空闲状态时,SCK 为低电平。
  • CPHA=1:SCK 第一个边沿移出数据,第二个边沿移入数据。

从图中可以看出,SCL 低电平空闲状态下,上升沿是在奇数边沿上,下降沿是在偶数边沿上。

3.3.3 工作模式 2

  • CPOL=1:空闲状态时,SCK 为高电平
  • CPHA=0:SCK 第一个边沿移入数据,第二个边沿移出数据
3.3.4 工作模式 3

在这里插入图片描述

  • CPOL=1:空闲状态时,SCK 为高电平
  • CPHA=1:SCK 第一个边沿移出数据,第二个边沿移入数据

标签:字节,主机,通信协议,SPI,从机,详解,边沿,数据
From: https://blog.csdn.net/Teminator_/article/details/141279117

相关文章

  • C++多线程详解 | 线程创建 | 互斥锁 | 条件变量 | 线程池
    目录前言1.线程创建2.互斥锁3.lock_guard与std::unique_lock4.condition_variable 5.线程池前言在说线程之前,先说说进程和线程的关系,以及什么是多线程(为了方便理解就用大白话来说)进程:进程就是运行中的程序,比如说一个微信的程序,你双击它,它运行起来了就是一个进程,在还......
  • C++ 模版详解 | 函数模板 | 类模版
    前言 什么是模板?模板是一个泛型编程的概念,即不考虑类型的一种编程方式,能够实现代码重用,提高效率模板可分为函数模板、类模板 模板的声明和定义模板的声明有两种,一种就是typename,另外一种就是使用class ,一般使用一种声明格式就可以了,不建议混合使用。template<typenam......
  • 专题1:树莓派Pico引脚功能详解
    1主要功能RaspberryPiPico一共有40个针脚。这是RaspberryPiPico官方提供的引脚图,应该有很多人看到上面的图标都是两眼一摸黑,接下来,我将从每种颜色分类来讲述每个引脚的功能2Power类引脚Power,顾名思义就是电源的意思。这种引脚一共有三个,Power类引脚是为接到Pico上......
  • 注解反射详解
    注解反射注解1.注解概述//什么是注解publicclassTest01extendsObject{//@Override重写的注解@OverridepublicStringtoString(){returnsuper.toString();}}2.内置注解//什么是注解@SuppressWarnings("all")//镇压警告publi......
  • Winform C#多显示器窗口控制详解
    写Winform程序的时候,有将一个窗口放置到特定的显示器,并且全屏的需求。于是借此机会,好好研究了一番这个Screen类[1],总结了一些方法。Windows的窗口逻辑首先我们需要知道窗口定位的逻辑。以2个窗口为例,下面的图片展示了显示器和坐标的对应关系。注意,使用深色模式可能看不清,可以点......
  • zynq QSPI flash分区设置&启动配置
    需求:一款基于zynq架构的产品,只有qspiflash,并没有其他的存储设备,现在的要求固化某个应用程序app,设置开机启动,但是根据厂家提供的sdk,编译出的镜像重启后,文件系统的内容都会还原,之前的方案是每次都要把程序放到buildroot下,然后重新编译,将rootfs、内核镜像、设备树打包到image.u......
  • Git 高级用法详解
    文章目录Git高级用法详解标签管理1.1创建标签1.2查看标签1.3推送标签变基操作(Rebase)2.1变基的基本操作2.2处理变基时的冲突2.3交互变基解决冲突3.1合并冲突3.2变基冲突撤销更改4.1撤销未提交的更改4.2撤回已提交的更改4.3重置分支与远程仓库交互5.1添加......
  • C++编程:内存栅栏(Memory Barrier)详解及在多线程编程中的应用
    文章目录0.引言1.什么是内存栅栏?2.为什么需要内存栅栏?本质原因是什么?2.1编译器优化2.2CPU乱序执行3.ARM64和x86架构下的内存栅栏差异3.1x86架构3.2ARM64架构4.代码示例4.1代码解析4.2memory_order_release和memory_order_acquire解释4.3为什么是“releas......
  • 操作符详解(二)
    目录1.逗号表达式2.下标访问[]、函数调用()1) []下标引用操作符2) 函数调用操作符3.结构成员访问操作符1)结构体2)结构的声明3)结构体变量的定义和初始化4)结构体成员的直接访问5)结构体成员的间接访问4.操作符的属性:优先级、结合性1)优先级2)结合性5. 表达......
  • 快速排序算法详解及Python实现
    目录引言快速排序算法步骤快速排序的Python实现性能分析注意事项引言快速排序(QuickSort)是一种高效的排序算法,由C.A.R.Hoare在1960年提出。它的基本思想是:通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据要小,然后再按此......