【转】SPI总线协议
SPI总线协议
概述
SPI(Serial Peripheral Interface)总线是主要应用于嵌入式系统内部通信的串行同步传输总线协议。通常为四线制的SPI总线支持全双工通信。SPI最初由Motorola在2000年提出,Motorola所定义的SPI标准为业界广泛引用,但不同半导体公司的实施细节可能有所不同,这些区别体现在寄存器设置、信号定义、数据格式等。业界没有统一的SPI标准,具体应用需要参考特定器件手册。
SPI协议特点包括主从模式、全双工通信、片选功能、模式错误标识及CPU中断、缓冲数据寄存器和可配置时钟相位极性等。SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据。也就是说,主设备通过对SCK时钟线的控制可以完成对通讯的控制。
应用
SPI以其简单高效应用于绝大多数SoC系统上,这些SoC通常同时支持作为主模式或从模式(二选一)。
FPGAs和其它专用芯片也广泛使用SPI传输数据。比如:
- 传感器:温度、压力传感器等
- 控制设备:音频编解码器等
- 通信设备:USB、以太网设备等
- 存储器:Flash、EEPROM等
- RTC时钟
- LCD设备
- MMC和SD卡
在高性能系统中,FPGAs通常使用SPI连接主从设备,比如连接外部传感器,和应用SPI加载配置。相比于JTAG,SPI定位用于高速配置(初始化)板上设备;而JTAG的初衷是为控制设备以相对低的准确度扫描和检测板上IO,在严格要求的场合,JTAG协议支持改变时钟占空比以满足建立和保持时间的要求。因此,JTAG并不定位于高速数据传输的场合。
优点和缺点
优点
- 支持全双工通信
- Push-Pull驱动性能相比Open Drain信号完整性更好,支持高速应用(100MHz以上)
- 协议支持字长不限于8bits,可根据应用特点灵活选择消息字长
- 硬件连接简单
- 只需要四根信号线(部分应用可以缩减到三根)
- 相比I2C和SMbus节省上拉电阻
- 相比I2C和SMbus不需要仲裁机制
- 从设备使用主设备时钟,节约时钟要求
- 从设备无需地址寻址
- 无需收发器
缺点
- 相比I2C两根线,SPI四根线更多
- 没有寻址机制,只能靠设备片选(chip select)选择不同从设备
- 没有数据流控制(但主设备可以通过延缓时钟边缘降低传输速度)
- 没有从设备接收数据ACK,主设备对于发送成功与否不得而知
- 典型应用只支持单主控
- 没有定义数据校验机制
- 没有统一的国际组织维护,变种多不利于不同厂商设备的互操作性(interoperability)
- 相比于RS232、RS422、RS485和CAN,SPI传输距离短
- 不支持热插拔
- 中断操作只能通过额外的信号线,或类似USB 1.1 and 2.0的Periodic Polling实现
内部框图
本文主要参考三家公司SPI协议手册,其原理大同小异:
- SPI Block Guide V04.01 -Motorola
- KeyStone Architecture Serial Peripheral Interface (SPI) User Guide -Texas Instruments
- TN0897: ST SPI protocol -STMicroelectronics
图1表示Motorola定义SPI模块的内部框图,其主要构成包括状态/控制/数据寄存器(Status,Control and Data Registers)、移位寄存器(Shifter Logic)、波特率发生器(Baud Rate Generator)、主从控制逻辑(Master/Slave Control Logic)和端口控制逻辑(Port Control Logic)。

图1. SPI模块框图(Motorola)
硬件基础
SPI总线定义两个及以上设备间的数据传输,提供时钟的设备为主设备(Master),接收时钟的设备为从设备(Slave)。
信号定义
SPI协议定义四根信号线,分别为:
- SCK : Serial Clock 串行时钟
- MOSI : Master Output, Slave Input 主发从收信号
- MISO : Master Input, Slave Output 主收从发信号
- SS : Slave Select 片选信号
其中MISO方向为从设备到主设备,其余三个信号均为主设备到从设备。
说明:
- 对于主设备,如果设置SS作为从设备的片选信号(最常用的场合),则它就不能用于多主设备应用的模式错误检测(参考SSOE和MODFEN寄存器设置,表1)
- SPI单个数据管脚支持双向模式。在双向模式下,主设备的MOSI,从设备的MISO作为双向IO(参考SPC0和BIDIROE寄存器设置,表2)
电路连接
图2表示基本的SPI设备连接示意图。片选信号SS通常低电平有效。SPI数据传输原理是基于主从设备内部移位寄存器的数据交换。在主设备SCK的控制下,待传数据由各自设备的数据寄存器(Data Register)传输到移位寄存器(Shift Register),再通过MOSI和MISO信号线完成主从设备间的数据交换。

图2. SPI主从模式传输示意图(电路)
主从设备间数据交换逻辑示意图如下图3所示:

图3. SPI主从模式传输示意图(逻辑)
硬件拓扑
单个主设备和单个从设备的SPI连接比较简单,以上图2和图3表示的就是这种拓扑结构。
通过多个片选信号(SS)或菊花链方式(Daisy Chain Configuration),单个主设备可以同时控制多个不同从设备。
- 片选方式
如图4示,每个从设备都需要单独的片选信号,主设备每次只能选择其中一个从设备进行通信。因为所有从设备的SCK、MOSI、MISO都是连在一起的,未被选中从设备的MISO要表现为高阻状态(Hi-Z)以避免数据传输错误。由于每个设备都需要单独的片选信号,如果需要的片选信号过多,可以使用译码器产生所有的片选信号。

图4. 主设备以片选方式控制多个从设备
- 菊花链方式
如图5示,数据信号经过主从设备所有的移位寄存器构成闭环。数据通过主设备发送(绿色线)经过从设备返回(蓝色线)到主设备。在这种方式下,片选和时钟同时接到所有从设备,通常用于移位寄存器和LED驱动器。注意,菊花链方式的主设备需要发送足够长的数据以确保数据送达到所有从设备。切记主设备所发送的第一个数据需(移位)到达菊花链中最后一个从设备。
菊花链式连接常用于仅需主设备发送数据而不需要接收返回数据的场合,如LED驱动器。在这种应用下,主设备MISO可以不连。如果需要接收从设备的返回数据,则需要连接主设备的MISO形成闭环。同样地,切记要发送足够多的接收指令以确保数据(移位)送达主设备。

图5. 主设备以菊花链方式控制多个从设备
电源管理
Motorola在SPI Block Guide中定义以下三种SPI电源模式:
- 运行模式 Run Mode
- 等待模式 Wait Mode
- 停止模式 Stop Mode
在运行模式下,SPI工作处于正常工作状态。通过修改SPICR1寄存器的SPE位更改此模式:
0: 禁用SPI模块(进入低功耗状态)
1: 使能SPI模块
在等待模式下,修改SPICR2寄存器的SPISWAI位:
0: 运行模式
1: 低功耗模式 SPI时钟停止运作
对于主设备,进入等待模式意味终止SPI总线上所有数据传输,唯有将SPISWAI 重新置为0方可恢复通信;对于从设备,进入等待模式后仍将与主设备保持同步,从设备数据的接收和发送还是正常的。
在停止模式下,对于主设备,进入停止模式意味着所有总线上通信的终止;对于从设备,进入停止模式后数据的发送和接收还是正常的,仍然与主设备保持同步状态。
TI在SPI User Guide定义两种低功耗状态:
- 全局低功耗模式 Global Low-Power Mode
- 局部低功耗模式 Local Low-Power Mode
全局低功耗模式受系统控制,此模式下SPI时钟停止,处于完全不作为状态。
通过写SPI全局寄存器(SPIGCR1)可以是SPI模块进入局部低功耗模式。此模式下,所有寄存器可以正常访问,但SPI的状态机处于停摆状态,数据收发可能异常。软件设置时需要注意不要在收发数据时让SPI进入低功耗模式。
寄存器说明
Motorola定义的SPI寄存器包括:
- SPI Control Register 1 (SPICR1)
- SPI Control Register 2 (SPICR2)
- SPI Baud Rate Register (SPIBR)
- SPI Status Register (SPISR)
- SPI Data Register (SPIDR)
其中除了状态寄存器SPISR为只读(Read-only),其它寄存器都是可读写的。通过往寄存器中写入不同的值,设置SPI模块的不同属性。
1. 控制寄存器1 SPICR1

图6. 控制寄存器1 SPICR1
SPIE — SPI Interrupt Enable Bit
1 = SPI interrupts enabled
0 = SPI interrupts disabled
SPE — SPI System Enable Bit
1 = SPI enabled, port pins are dedicated to SPI functions
0 = SPI disabled (lower power consumption)
SPTIE — SPI Transmit Interrupt Enable
1 = SPTEF interrupt enabled
0 = SPTEF interrupt disabled
MSTR — SPI Master/Slave Mode Select Bit
1 = SPI is in Master mode
0 = SPI is in Slave mode
CPOL — SPI Clock Polarity Bit
1 = Active-low clocks selected. In idle state SCK is high
0 = Active-high clocks selected. In idle state SCK is low
CPHA — SPI Clock Phase Bit
1 = Sampling of data occurs at even edges (2,4,6,...,16) of the SCK clock
0 = Sampling of data occurs at odd edges (1,3,5,...,15) of the SCK clock
SSOE — Slave Select Output Enable
SSOE 用于主设备设置SS管脚功能,它和MODFEN组合决定主设备SS管脚功能。如表1所示其功能组合:

表1. SS输入/输出选择
LSBFE — LSB-First Enable
1 = Data is transferred least significant bit first
0 = Data is transferred most significant bit first
2. 控制寄存器2 SPICR2
图7. 控制寄存器1 SPICR2
MODFEN — Mode Fault Enable Bit
1 = SS port pin with MODF feature
0 = SS port pin is not used by the SPI
BIDIROE — Output enable in the Bidirectional mode of operation
控制双向模式(Bidirectional Mode)下主设备的MOSI和从设备MISO的输出缓冲器
1 = Output buffer enabled
0 = Output buffer disabled
SPISWAI — SPI Stop in Wait Mode Bit
1 = Stop SPI clock generation when in wait mode
0 = SPI clock operates normally in wait mode
SPC0 — Serial Pin Control Bit 0
控制(单个)数据管脚是否配置为双向模式,与BIDIROE组合控制(单个)数据管脚同时支持收发功能(如下表2)

表2. MOSI/MISO双向管脚配置
3. 波特率寄存器 SPIBR
图8. 波特率寄存器 SPIBR
SPPR2–SPPR0 — SPI Baud Rate Preselection Bits
SPR2–SPR0 — SPI Baud Rate Selection Bits
以上五个寄存器通过下面公式决定波特率除数因子(BaudRateDivisor),进而决定SCK时钟频率。
除数因子:(通过五个参数计算出来的除数因子不仅包括2^N,还包括4/6/10等总计64个组合)

计算波特率:

举例,SPPR[2:0]设为101,SPR[2:0]设为000,计算得除数因子(5+1) * (2^1) = 12。如果系统时钟速率为25MHz,则SCK时钟速率 = 25MHz/12 = 2.0833MHz.
4. 状态寄存器 SPISR

图9. 状态寄存器 SPISR
SPISR表征SPI传输状态,只可读,不可写。
SPIF — SPIF Interrupt Flag
数据byte写入SPI数据寄存器后,此位被置为1。读取数据寄存器后,此位清零。
1 = New data copied to SPIDR
0 = Transfer not yet complete
SPTEF — SPI Transmit Empty Interrupt Flag
1 = SPI Data register empty 表示发送数据寄存器为空,可以接收待发送数据
0 = SPI Data register not empty 此时忽略任何写入数据寄存器的指令
MODF — Mode Fault Flag
如表1,错误检测功能使能后,MODF表示检测到SPI模式错误。
1 = Mode fault has occurred.
0 = Mode fault has not occurred
根据Motorola的定义,SPI仅提供一种错误——即模式错误(Mode Fault Error)——的检测机制,通过SS管脚状态判断SPI总线上是否存在两个及以上的设备同时驱动SCK和MOSI。模式错误检测仅适用于主设备(前提是在寄存器中激活此功能)。对于从设备,SS总是作为片选信号的。
在发生模式错误后(MODF = 1),系统通过写入控制寄存器SPICR1(使设备由Master改为Slave模式,SCK、MISO和MOSI表现为高阻态以避免与总线上其它驱动设备冲突),随后系统自动将此bit置为零(MODF = 0)。
5. 数据寄存器 SPIDR

图10. 数据寄存器 SPIDR
SPIDR作为SPI收发两用的寄存器,数据在写入SPIDR后进入待传输队列,队列中的数据字节在前面数据传输结束后立即进行传输。状态寄存器SPISR的SPTEF位表示数据寄存器可以接收新数据。数据寄存器接收数据完毕后将SPIF置为1。
如果SPIF已经置为1,但服务并未运行(not serviced),则下一个(第二个)接收的数据字节将暂存在移位寄存器中直到下次传输。数据寄存器中的数据字节不变。
如果SPIF已经置为1,并且移位寄存器中已经暂存数据(即第二个数据字节),并且SPIF服务在第三个数据字节传输前完成,则移位寄存器中的数据(即第二个数据字节 )正常写入数据寄存器,SPIF仍保持置位状态(高),如图11所示;

图11. SPIF服务及时完成
如果SPIF已经置为1,并且移位寄存器中已经暂存数据(即第二个数据字节),并且SPIF服务在第三个数据字节传输后完成,则移位寄存器中的数据(即第二个数据字节 )遭破坏,不能正常写入到数据寄存器,SPIF仍保持置位状态(高),如图12所示 。

图12. SPIF服务未及时完成
SPI传输模式
通过设置控制寄存器SPICR1中的CPOL和CPHA位,将SPI可以分成四种传输模式。
CPOL,即Clock Polarity,决定时钟空闲时的电平为高或低。对于SPI数据传输格式没有显著影响。
1 = 时钟低电平时有效,空闲时为高
0 = 时钟高电平时有效,空闲时为低
CPHA,即Clock Phase,定义SPI数据传输的两种基本模式。
1 = 数据采样发生在时钟(SCK)偶数(2,4,6,...,16)边沿(包括上下边沿)
0 = 数据采样发生在时钟(SCK)奇数(1,3,5,...,15)边沿(包括上下边沿)
四种模式如下图13所示。先看第一列两张图(CPHA = 0),采样发生在第一个时钟跳变沿,即数据采样发生在SCK奇数边沿;再看第二列(CPHA =1),采样发生在第二个时钟跳变沿,即数据采样发生在SCK偶数边沿。第一行两张图(CPOL = 0),SCK空闲状态为低电平,第二行两张图(CPOL = 1),SCK空闲状态为高电平。
主从设备进行SPI通讯时,要确保它们的传输模式设置相同。对于某些场合,可能需要调整CPOL/CPHA设置以满足设备特定要求。

图13. SPI四种传输模式
时序要求
具体时序要求参考器件手册。以下Motorola标准对CPHA = 0(图14)和CPHA =1(图15)不同设置时序的简要说明:
CPHA = 0
- 有些器件在片选后数据立即出现在MOSI/MISO管脚,数据锁存于第一个时钟边沿
- 片选SS先于SCK半个时钟有效
- 在SCK的第二个时钟边沿,上个时钟边沿锁存的数据写入移位寄存器(MSB或LSB)
- 以此类推,数据在奇数边沿锁存,在偶数边沿写入移位寄存器
- 经过16个时钟边沿后,串行传输的数据全部写入(并行的)移位寄存器,完成主从设备的数据交换

图14. SPI时钟模式(CPHA = 0)
CPHA = 1
- 有些设备要求数据输出在SCK第一个时钟边沿之后,数据锁存于第二个时钟边沿
- 片选SS先于SCK半个时钟有效
- 在SCK的第三个时钟边沿,上个时钟边沿锁存的数据写入移位寄存器(MSB或LSB)
- 以此类推,数据在偶数边沿锁存,在奇数边沿写入移位寄存器
- 经过16个时钟边沿后,串行传输的数据全部写入(并行的)移位寄存器,完成主从设备的数据交换

图15. SPI时钟模式(CPHA = 1)
SPI通信过程
简要说明ST和Spansion器件的SPI通讯过程。
1. STMicroelectronics
ST SPI规范定义,在系统启动后,主设备读取从设备8位SPI寄存器以确定从设备字长(16,24或32bit)及其它特性。每个帧(读/写)包括1个操作字节(Instruction Byte)和紧接着的1-3个数据字节(Data Byte)。
操作字节可能是指令字节或全局状态字节。记住指令字节总是出现在(主从)设备的输入管脚(SDI),全局状态字节总是出现在(主从)设备的输出管脚(SDO)。
- Command Byte 指令字节

图16. 指令字节格式
指令字节前2位OC0/OC1指定SPI操作的四种类型,包括写操作、读操作、读和复位状态操作、读取设备信息操作;
指令字节后6位Ax指定操作对象(RAM/ROM)的地址。
- Global Byte 全局状态字节

图17. 全局状态字节格式
指示设备状态信息,如工作模式、通讯错误等。
如下图18读写操作数据帧格式。对于写操作,SDO输出全局变量字节之后紧接着地址寄存器中先前缓存的数据;对于读操作,全局变量字节后紧接着寻址待取的数据。

图18. SPI读写操作(ST)
2. Spansion
以常见的SPI接口Flash为例。如图19所示,在CS#低有效后,基于操作模式,决定在SCK的上升或下降沿触发采样数据。8位指令字节后紧接着24位地址,寻址Flash内部存储块。随着Flash容量增大,可能需要更多的寻址位。比如Micron的N25Q等器件,需要使能4 Byte地址模式以支持容量在128Mbit以上的器件。(单个地址寻址对应1 Byte数据,则24位地址寻址最大2^24 = 16 M Byte = 128Mbit)。

图19. SPI读操作(Spansion Flash)
复位和中断
复位后,寄存器值恢复初始状态(以上寄存器表下方所列出)。对于从设备,如果复位后不对SPIDR写入数据,它将输出随机数据或复位前从主设备接收到的数据;复位后SPIDR的数据全部清零。
SPI的中断向量和优先级因设备而异。中断请求由状态寄存器SPISR中MODF、SPIF和SPTEF位逻辑或产生。
协议分析
利用示波器或逻辑分析仪的SPI协议分析功能(电气特性 & 译码),可以快速定位通信链路上出现的问题。示波器支持不同的触发方式,以Tektronix示波器为例,其支持SPI的触发方式包括:
- SS触发,基于片选信号状态变化触发
- SOF触发,根据时钟空闲时间确定Start Of a Frame触发
- MOSI触发,基于MOSI上特定的数据格式触发
- MISO触发,基于MISO上特定数据格式触发
- MOSI/MISO触发,基于MOSI和MISO上特定数据格式触发
I2C & JTAG
SPI和I2C,JTAG对比参考表3:

表3. SPI, I2C和JTAG协议概览
参考资料
1. Serial Peripheral Interface Bus -Wikipedia
2. SPI Block Guide V04.01 -Motorola
3. KeyStone Architecture User Guide: Serial Peripheral Interface, Literature Number: SPRUGP2A -Texas Instruments
4. TN0897: ST SPI Protocol -STMicroelectronics
5. Comparing Serial Interfaces -Spansion
6. Serial Peripheral Interface Tutorial -Sparkfun
7. Debugging Serial Buses in Embedded System Designs -Tektronix
【转】SPI总线协议的更多相关文章
- SPI总线协议及SPI时序图详解
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚 ...
- SPI总线协议及SPI时序图详解【转】
转自:https://www.cnblogs.com/adylee/p/5399742.html SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接 ...
- 关于I2C和SPI总线协议【转】
关于I2C和SPI总线协议 IICvs SPI 现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral ...
- spi 总线协议记录
摘抄至: http://blog.csdn.net/skyflying2012/article/details/11710801 概述: SPI, Serial Perripheral Interfa ...
- SPI总线协议理解
1.什么是SPI: 是摩托罗拉公司设计的一种全双工通信.高速的.同步的串行外部设备通信协议. 2.SPI作用: 用于设备之间的数据交互. 3.SPI由什么构成: 1)MOSI:主设备输出从设备输入线, ...
- SPI总线协议介绍
http://blog.csdn.net/ce123_zhouwei/article/details/6897293 https://www.cnblogs.com/yangguang-it/p/71 ...
- SPI、I2C、UART三种串行总线协议的区别
第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART(Universal Asynchronous R ...
- SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)
SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...
- MSP430单片机的两种SPI总线实现方式
MSP430单片机上的SPI总线的实现方式分为两种:硬件实现和软件实现. 二者的抽象层次不同,硬件实现方式下程序员只需要完成总线协议的寄存器层,即一字节(char,8位二进制)数据,而软件实现方式下程 ...
随机推荐
- excel实用技巧——vlookup函数
1.VLOOKUP函数的套路 VLOOKUP(要找谁,在哪儿找,返回第几列的内容,精确找还是近似找) 最后一个参数: 如果为0或FASLE,用精确匹配方式,而且支持无序查找: 如果为TRUE或被省略, ...
- 20155227《网络对抗》Exp2 后门原理与实践
20155227<网络对抗>Exp2 后门原理与实践 基础问题回答 (1)例举你能想到的一个后门进入到你系统中的可能方式? 在非官方网站下载软件时,后门很可能被捆绑在软件中. 攻击者利用欺 ...
- Getting Start chrome-extension demo
写一个小小的chrome扩展demo~ 准备工作 了解一下插件chrome-extension: 在应用商店里的插件基本上都是以.crx为文件后缀,该文件其实就是一个压缩包,包括插件所需要的html. ...
- LCA的一些算法
LCA,就是求树上任意两点的最近公共祖先 (本题图片与代码均为Luogu3379) 方法我好像讲过一个,这次把主要的三个一起讲一讲 <1> 倍增(O(n log n)) 我们先考虑最基本的 ...
- Nuxt.js + koa2 入门
1. nuxt项目初始化 下面是使用 koa 模板方法初始化一个项目,使用该方法需要将 nuxt 的版本降至1.4.2: 官方 https://zh.nuxtjs.org/guide/installa ...
- 用C语言操作MySQL数据库,进行连接、插入、修改、删除等操作
C/C++ code ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 3 ...
- Jq_SetTimeOut
倒计时 59 秒: var t function timedCount() { document.getElementById('txt').value=c ){ c--; }else{ clearT ...
- kubernetes(k8s) 的常用命令
1.查询副本[root@master ~]# kubectl get pods2.删除一个副本[root@master ~]# kubectl get pods 3.启动一个容器副本[root@mas ...
- 二叉树 c++
树 非空树 有一个(root)根节点r 其余节点可分为m个互不相交的有限集(子树)T1....Tm 具有n个节点的树,具有(n-1)条连接(指针域),需要构成结构体,尽可能减少空间域的浪费,使用儿子兄 ...
- 3. Python3 基本数据类型
Python3 基本数据类型 Python 中的变量不需要声明.每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建. 在 Python 中,变量就是变量,它没有类型,我们所说的"类型& ...