目录
前言
本文摘抄于野火开发指南,仅用于学习过程的记录,如有侵权请联系删除。
1.SPI简介
SPI 是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口。是 Motorola 首先在其 MC68HCXX 系列处理器上定义的。SPI 接口主要应用在 EEPROM,FLASH,实时时 钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。SPI 是一种高速的,全双工,同 步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局上 节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协 议,STM32F1 也有 SPI 接口。
SPI 接口一般使用
4
条线通信:
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。
SPI 主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可
编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
SPI 总线四种工作方式
SPI
模块为了和外设进行数据交换,根据外设工作要求,其输出串
行同步时钟极性和相位可以进行配置,时钟极性(
CPOL
)对传输协议没有重大的影响。如果
CPOL=0
,串行同步时钟的空闲状态为低电平;如果
CPOL=1
,串行同步时钟的空闲状态为高电
平。时钟相位(
CPHA
)能够配置用于选择两种不同的传输协议之一进行数据传输。如
CPHA=0
,
在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果
CPHA=1
,在串行同步时钟
的第二个跳变沿(上升或下降)数据被采样。
SPI
主模块和与之通信的外设备时钟相位和极性
应该一致。
不同时钟相位下的总线数据传输时序如图
所示:
SPI
通讯设备之间的常用连接方式见
图
2.SPI协议
与 I2C
的类似,
SPI
协议定义了通讯的
起始和停止信号、数据有效性、时钟同步等环节
。
2.1 SPI基本通讯过程
先看看 SPI
通讯的通讯时序,见
图
这是一个主机的通讯时序。
NSS
、
SCK
、
MOSI
信号都由主机控制产生,而
MISO
的信号由从机
产生,主机通过该信号线读取从机的数据。
MOSI
与
MISO
的信号只在
NSS
为低电平的时候才有
效,在
SCK
的每个时钟周期
MOSI
和
MISO
传输一位数据。
以上通讯流程中包含的各个信号分解如下:
2.2通讯的起始信号和停止信号
在图
中的标号处,
NSS
信号线由高变低,是
SPI
通讯的起始信号。
NSS
是每个从机各自独
占的信号线,当从机在自己的
NSS
线检测到起始信号后,就知道自己被主机选中了,开始准备
与主机通讯。在图中的标号处,
NSS
信号由低变高,是
SPI
通讯的停止信号,表示本次通讯结束, 从机的选中状态被取消。
2.3数据有效性
SPI 使用
MOSI
及
MISO
信号线来传输数据,使用
SCK
信号线进行数据同步。
MOSI
及
MISO
数 据线在 SCK
的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时,
MSB 先行或 LSB
先行并没有作硬性规定,但要保证两个
SPI
通讯设备之间使用同样的协定,一般都会采用图
中的
MSB
先行模式。 观察图中的标号处,MOSI
及
MISO
的数据在
SCK
的上升沿期间变化输出,在
SCK
的下降沿时 被采样。即在 SCK
的下降沿时刻,
MOSI
及
MISO
的数据有效,高电平时表示数据“
1
”,为低电 平时表示数据“0
”。在其它时刻,数据无效,
MOSI
及
MISO
为下一次表示数据做准备。 SPI 每次数据传输可以
8
位或
16
位为单位,每次传输的单位数不受限制。
2.4 CPOL/CPHA及通讯模式
上面讲述的图
中的时序只是
SPI
中的其中一种通讯模式,
SPI
一共有四种通讯模式,它们的 主要区别是总线空闲时 SCK
的时钟状态以及数据采样时刻。为方便说明,在此引入“时钟极性 CPOL”和“时钟相位
CPHA
”的概念。
时钟极性 CPOL 是指
SPI
通讯设备处于空闲状态时,
SCK
信号线电平信号
(
即
SPI
通讯开始前、 NSS 线为高电平时
SCK
的状态
)
。
CPOL=0
时,
SCK
在空闲状态时为低电平,
CPOL=1 时,则相反。
时钟相位 CPHA
是指数据的采样的时刻,当
CPHA=0
时,
MOSI
或
MISO
数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当
CPHA=1
时,数据线在
SCK
的“偶数边沿”采样。见
图:
CPHA=0 时的 SPI 通讯模式
当
CPHA=1
时,不受
CPOL
的影响,数据信号在
SCK
的偶数边沿被采样
CPHA=1 时的 SPI 通讯模式
由
CPOL
及
CPHA
的不同状态,
SPI
分成了四种模式,见表
,主机与从机需要工作在相同的
模式下才可以正常通讯,实际中采用较多的是“模式
0
”与“模式
3
”
SPI 的四种模式:
3.STM32的SPI特性及架构
3.1STM32的SPI外设简介
STM32 的
SPI
外设可用作通讯的主机及从机,支持最高的
SCK
时钟频率为
f
pclk
/2 (STM32F103
型 号的芯片默认 f:sub:
pclk1
为
36MHz
,
f
pclk2
为
72MHz)
,完全支持
SPI
协议的
4
种模式,数据帧长 度可设置为 8
位或
16
位,可设置数据
MSB
先行或
LSB
先行。它还支持双线全双工
(
前面小节说 明的都是这种模式)
、双线单向以及单线模式。其中双线单向模式可以同时使用
MOSI
及
MISO
数 据线向一个方向传输数据,可以加快一倍的传输速度。而单线模式则可以减少硬件接线,当然这样速率会受到影响。
3.2STM的SPI架构剖析
3.3通讯引脚
SPI 的所有硬件架构都从图
24‑5
中左侧
MOSI
、
MISO
、
SCK
及
NSS
线展开的。
STM32
芯片有多 个 SPI
外设,它们的
SPI
通讯信号引出到不同的
GPIO
引脚上,使用时必须配置到这些指定的引 脚,见表
。关于
GPIO
引脚的复用功能,可查阅《
STM32F10x
规格书》,以它为准
其中 SPI1
是
APB2
上的设备,最高通信速率达
36Mbtis/s
,
SPI2
、
SPI3
是
APB1
上的设备,最高 通信速率为 18Mbits/s
。除了通讯速率,在其它功能上没有差异。其中
SPI3
用到了下载接口的引 脚,这几个引脚默认功能是下载,第二功能才是 IO
口,如果想使用
SPI3
接口,则程序上必须先 禁用掉这几个 IO
口的下载功能。一般在资源不是十分紧张的情况下,这几个
IO
口是专门用于下 载和调试程序,不会复用为 SPI3
。
3.4时钟控制逻辑
SCK 线的时钟信号,由波特率发生器根据“
控制寄存器
CR1
”中的
BR[0:2]
位
控制,该位是对
f
pclk 时钟的分频因子,对 f
pclk
的分频结果就是
SCK
引脚的输出时钟频率,计算方法见表
。
其中的 fpclk 频率是指 SPI 所在的 APB 总线频率,APB1 为 fpclk1,APB2 为 fpckl2。
通过配置“控制寄存器
CR
”的“
CPOL
位”及“
CPHA
”位可以把
SPI
设置成前面分析的
4
种
SPI 模式
。
3.5数据控制逻辑
SPI 的
MOSI
及
MISO
都连接到数据移位寄存器上,数据移位寄存器的数据来源及目标接收、发 送缓冲区以及 MISO
、
MOSI
线。当向外发送数据的时候,数据移位寄存器以“发送缓冲区”为数 据源,把数据一位一位地通过数据线发送出去;当从外部接收数据的时候,数据移位寄存器把数 据线采样到的数据一位一位地存储到“接收缓冲区”中。通过写 SPI
的“数据寄存器
DR
”把数 据填充到发送缓冲区中,通讯读“数据寄存器 DR
”,可以获取接收缓冲区中的内容。其中数据帧 长度可以通过“控制寄存器 CR1
”的“
DFF
位”配置成
8
位及
16
位模式;配置“
LSBFIRST
位” 可选择 MSB
先行还是
LSB
先行。
3.6整体控制逻辑
整体控制逻辑负责协调整个 SPI
外设,控制逻辑的工作模式根据我们配置的“控制寄存器(CR1/CR2)”的参数而改变,基本的控制参数包括前面提到的
SPI
模式、波特率、
LSB
先行、主 从模式、单双向模式等等。在外设工作时,控制逻辑会根据外设的工作状态修改“状态寄存器 (SR)”,我们只要读取状态寄存器相关的寄存器位,就可以了解
SPI
的工作状态了。除此之外,控 制逻辑还根据要求,负责控制产生 SPI
中断信号、
DMA
请求及控制
NSS
信号线。
实际应用中,我们一般不使用 STM32 SPI 外设的标准
NSS
信号线,而是更简单地使用普通的 GPIO,软件控制它的电平输出,从而产生通讯起始和停止信号。
3.7通讯过程
STM32 使用
SPI
外设通讯时,在通讯的不同阶段它会对“状态寄存器
SR
”的不同数据位写入参 数,我们通过读取这些寄存器标志来了解通讯状态。
图 中的是“主模式”流程,即 STM32 作为 SPI 通讯的主机端时的数据收发过程。
图中
主发送器通讯过程
主模式收发流程及事件说明如下:
(1) 控制
NSS
信号线,产生起始信号
(
图中没有画出
)
;
(2) 把要发送的数据写入到“数据寄存器
DR
”中,该数据会被存储到发送缓冲区;
(3) 通讯开始,
SCK
时钟开始运行。
MOSI
把发送缓冲区中的数据一位一位地传输出去;
MISO 则把数据一位一位地存储进接收缓冲区中;
(4) 当发送完一帧数据的时候,“状态寄存器
SR
”中的“
TXE
标志位”会被置
1
,表示传输完一
帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“
RXNE
标志位”会被置
1
,表示传输
完一帧,接收缓冲区非空;
(5) 等待到“
TXE
标志位”为
1
时,若还要继续发送数据,则再次往“数据寄存器
DR
”写入数据即可;等待到“RXNE
标志位”为
1
时,通过读取“数据寄存器
DR
”可以获取接收缓冲区中的 内容。
假如我们使能了 TXE
或
RXNE
中断,
TXE
或
RXNE
置
1
时会产生
SPI
中断信号,进入同一个中 断服务函数,到 SPI
中断服务程序后,可通过检查寄存器位来了解是哪一个事件,再分别进行处 理。也可以使用 DMA
方式来收发“数据寄存器
DR
”中的数据。
4.SPI初始化结构体详解
typedef struct {uint32_t Mode;/* 设置 SPI 的主 / 从机端模式 */uint32_t Direction; /* 设置 SPI 的单双向模式 */uint32_t DataSize;/* 设置 SPI 的数据帧长度,可选 8/16 位 */uint32_t CLKPolarity; /* 设置时钟极性 CPOL ,可选高 / 低电平 */uint32_t CLKPhase; /* 设置时钟相位,可选奇 / 偶数边沿采样 */uint32_t NSS;/* 设置 NSS 引脚由 SPI 硬件控制还是软件控制 */uint32_t BaudRatePrescaler; /* 设置时钟分频因子, fpclk/ 分频数 =fSCK */uint32_t FirstBit; /* 设置 MSB/LSB 先行 */uint32_t TIMode;/* 指定是否启用 TI 模式 */uint32_t CRCCalculation; /* 指定是否启用 CRC 计算 */uint32_t CRCPolynomial;/* 设置 CRC 校验的表达式 */} SPI_InitTypeDef;
这些结构体成员说明如下,其中括号内的文字是对应参数在
STM32
标准库中定义的宏:
(1) Mode
:
本成员设置
SPI
工作在
主机模式
(SPI_MODE_MASTER)
或
从机模式 (SPI_MODE
_SLAVE ),这两个模式的最大区别为 SPI 的 SCK 信号线的时序,
SCK 的时序是由通讯中的主机产生的。若被配置为从机模式,STM32 的 SPI 外设将接受外来的 SCK 信号。
(2) Direction
:本成员设置
SPI
的通讯方向,可设置为双线全
(SPI_DIRECTION_2LINES)
,双 线只接收 (SPI_DIRECTION_2LINES_RXONLY)
,单线
SPI_DIRECTION_1LINE
。
(3) DataSize
:
本成员可以选择
SPI
通讯的数据帧大小是为
8
位
(SPI_DATASIZE_8BIT)
还是
16 位 (SPI_DATASIZE_16BIT)
。
(4) CLKPolarity 和
CLKPhase
:这两个成员配置
SPI
的时钟极性
CLKPolarity
和时钟相位 CLKPhase ,这两个配置影响到
SPI
的通讯模式,关于
CLKPolarity
和
CLKPhase
的说明参考前
面“
通讯模式
”小节。时钟极性
CLKPolarity
成员,可设置为高电平
(SPI_POLARITY_HIGH) 或低电平 (SPI_POLARITY_LOW)
。时钟相位
CPHA
则可以设置为
SPI_PHASE_1EDGE(
在 SCK 的奇数边沿采集数据
)
或
SPI_P HASE_2EDGE(
在
SCK
的偶数边沿采集数据
)
。
(5) NSS
:
本成员配置
NSS
引脚的使用模式,可以选择为
硬件模式
(SPI_NSS_HARD )
与
软件模 式 ( SPI_NSS_SOFT )
,在硬件模式中的
SPI
片选信号由
SPI
硬件自动产生,而软件模式则需 要我们亲自把相应的 GPIO
端口拉高或置低产生非片选和片选信号。实际中软件模式应用
比较多。
(6) BaudRatePrescaler
:
本成员设置波特率分频因子,分频后的时钟即为
SPI
的
SCK
信号线的时 钟频率。这个成员参数可设置为 fpclk
的
2
、
4
、
6
、
8
、
16
、
32
、
64
、
128
、
256
分频。
(7) FirstBit
:
所有串行的通讯协议都会有
MSB
先行
(
高位数据在前
)
还是
LSB
先行
(
低位数据在 前)
的问题,而
STM32
的
SPI
模块可以通过这个结构体成员,对这个特性编程控制。
(8) TIMode :指定是否启用
TI
模式。可选择为使能
( SPI_TIMO DE_ENABLE )
与不是能
( SPI_TIMODE_DISABLE )
。
(9) CRCCalculation :指定是否启用
CRC
计算
(10) SPI_CRCPolynomial
:
这是
SPI
的
CRC
校验中的多项式
,若我们使用
CRC
校验时,就使用这 个成员的参数 (
多项式
)
,来计算
CRC
的值。
配置完这些结构体成员后,我们要调用 HAL_SPI_Init 函数把这些参数写入到寄存器中,实现
SPI 的初始化,然后调用 __HAL_SPI_ENABLE
来使能
SPI
外设。