STM32 SPI通信

发布于:2024-04-29 ⋅ 阅读:(32) ⋅ 点赞:(0)

一、SPI总线简介

1.1 SPI总线

        串口外设接口(Serial Peripheral Interface,SPI)总线是一种同步串行外设接口,允许MCU与各种外围设备进行全双工、同步串行通信

SPI总线有四根通信线:

①SCKSerial Clock,串行时钟):作为主设备的输出、从设备的输入

②MOSI(Master Output Slave Input):主设备发送数据,从模式接收数据

③MISO(Master Input Slave Output):主设备接收数据,从模式发送数据

④SS(Slave Select,片选引脚,低电平有效):选择从机,让主设备可以单独地与特定从设备通信,避免数据线上地冲突

        SPI总线采用主从模式(Master - Slave)架构,支持总线挂载多设备(一主多从),被广泛应用于MCU和外设模块(如E2PROM、ADC、显示驱动器等)

        在大容量和互联型产品上,SPI可以配置为支持SPI协议或者支持I²S音频协议

1.2 SPI硬件电路

所有SPI设备的SCKMOSIMISO分别连在一起

主机另外引出多条SS控制线,分别接到各从机的SS引脚

输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

为了避免一个主机输入,其他从机均为推挽输出,导致的总线冲突:SPI规定,当从机SS引脚为高电平时,其输出引脚必须切换为高阻态

1.3 SPI通信原理

        SPI为环形总线结构。通信总是由主机发起,在同步SCK驱动下,主机移位寄存器的最高位数据通过MOSI移位到从机移位寄存器的最低位,而从机移位寄存器的最高位数据通过MISO移位到主机移位寄存器的最低位。循环上述过程8次,则通信一个字节数据

1.4 SPI通信时序

1.4.1 起始与终止

1.4.2 交换模式

根据CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)两位组合,共有四种组合模式

(1)模式0(常用)

CPOL = 0空闲时SCK为低电平

CPHA = 0:第一个边沿(上升沿)移入(采样)数据,第二个边沿(下降沿)移出数据

对于传输的首个数据的最高位,在SS的下降沿就将其移出,之后在SCL的(上升沿)移入(采样)

(2)模式1

CPOL = 0空闲时SCK为低电平

CPHA = 1上升沿移出数据下降沿移入(采样)数据

(3)模式2

CPOL = 1空闲时SCK为高电平

CPHA = 0:第一个边沿(上升沿)移入(采样)数据,第二个边沿(下降沿)移出数据

对于传输的首个数据的最高位,在SS的下降沿就将其移出,之后在SCL的(上升沿)移入(采样)

(4)模式3

CPOL = 1空闲时SCK为高电平

CPHA = 1上升沿移出数据下降沿移入(采样)数据

1.5 SPI数据格式

SPI:指令码(芯片厂商规定)+寄存器地址+数据

(1)发送指令

向SS指定的设备,发送指令(0x06

(2)指定地址写

向SS指定的设备,发送写指令(0x02), 随后在指定地址(Address[23:0])下,写入指定数据(Data

(3)指定地址读

向SS指定的设备,发送读指令(0x03),随后在指定地址(Address[23:0])下,读取从机数据(Data

二、W25Q64存储器芯片

2.1 W2Q564简介

        时钟频率:160MHz(Dual SPI,双重SPI等效的时钟频率),该存储器的芯片将SPI进行了改进:MOSI和MISO可以同时发送或者同时接收,数据传输速率相当于普通SPI通信模式的2

        320MHz(Quad SPI,四重SPI等效的时钟频率),MOSI、MISO、WP(写保护)、HOLD,四个引脚同时收发数据,数据传输速率相当于普通SPI通信模式的4

2.2 硬件电路

2.3 W2Q564结构框图

        存储空间的划分:先划分为若干的块(Block),其中每一块再划分为若干的扇区(Sector),对于一个扇区,内部还可以分成很多页(Page)

        W2Q564一共有8MByte的存储空间(00 0000H ~ 7F FFFFH),其中,每块定义占用内存64KB,可分为128块;每扇区定义占用内存4KB,可分为16个扇区;每页定义占用内存256B,可分为16页

块Block(0~127,64KB):地址变化规律 :xx 0000H ~  xx FFFFH(xx:最高两位表示位于某一块,变化范围:00~7F

扇区Sector(0~15,4KB):地址变化规律:xx k000H ~  xx kFFFH(k:第四位表示位于某一扇区,变化范围:0~F)

页Page(0~16,256B):地址变化规律:xx xj00H ~  xx xjFFH(k:第三位表示位于某一页,变化范围:0~F)

2.4 状态寄存器

写使能:WEL = 1,表示可以进行写操作

写失能:WEL = 0

(1)上电后,芯片默认写失能

(1)执行以下指令:写失能、页编程、扇区擦除

在任何写操作前,都需要来一遍写使能

一个写使能,只能保证后续的一条指令可以执行

2.5 指令集

三、SPI外设

STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担

(1)8位或16位传输帧格式选择

(2)可编程的时钟极性、时钟相位和数据传输顺序(高位先行 or 低位先行)

(3)时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)

(4)支持全双工同步、或者半双工/单工同步通信

(5)支持多主机模式

(6)支持DMA功能的1字节发送和接收缓冲器,产生发送和接收请求

(7)支持可靠通信的硬件CRC

(8)兼容I²S协议(仅在大容量和互联型产品)

STM32F103C8T6 硬件SPI资源:SPI1SPI2

SPI主模式:

        数据发送:当写入数据至发送缓冲器时,发送开始。在发送第一个数据位时,数据字被并行地传入移位寄存器,而后串行的移出到MOSI引脚上,MSB(高位)在先还是LSB(低位)在先,取决于SPI_CR1中LSBFIRST位的设置。当时据从发送缓冲器传输到移位寄存器时,TXE置1,如果设置了SPI_CR1中的TXEIE,将产生中断

        数据接收:当数据传输完成时,传送移位寄存器中的数据到接收缓冲器,并且RXNE被置1。如果设置了SPI_CR1中的RXNEIE,将产生中断。当读SPI_DR时,将返回接收缓冲器中的数据,同时RXNE被置0

主模式全双工连续传输:

在模式3下,TXE为1时,数据写入发送缓冲器,此时,发送缓冲器的数据并行传送到移位寄存器

TXE为0,数据开始传输,并将下一位数据写入发送缓冲器,等待第一个数据发送完成

当第一个数据发送完成,交换的数据被接收,放到了接收缓冲器中,并将RXNE置1。

当第二个数据发送完成,交换的数据被接收,放到了接收缓冲器中,并将RXNE置1。

简易流程:

(1)等待TXE为1,写入数据,之后TXE为0

(2)数据移入移位寄存器,TXE为1,下一个数据移入发送缓冲器等待,此时,TXE为1

(3)第一个数据发送完成后,交换的数据从移位寄存器,并行传送到接收缓冲器,将RXNE置1

(4)与此同时,第二个数据迅速转移到移位寄存器,此时TXE为1

(5)接着,将下一位数据写入发送缓冲器中,此时,TXE为1

主模式全双工非连续传输:

(1)等待TXE为1,写入发送数据

(2)等待RXNE为1,接收数据

连续传输优点:传输效率高,性能强大

缺点:软件设计复杂

非连续传输优点:软件设计简单,易于理解

缺点:传输效率相对较低,在字节与字节之间会出现间隙,且随着时钟频率的增快而变长

四、SPI相关库函数

(1)初始化:SPI_Init()

(2)传送数据:SPI_SendData ()

(3)接收数据:SPI_ReceiveData()

五、SPI外设基本配置

(1)开启SPI、GPIO的时钟

(2)配置GPIO的模式

(3)配置SPI外设,完成初始化

	SPI_InitTypeDef SPI_InitStruct;
	SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;  //波特率分频系数
	SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;  //时钟相位
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;  //时钟极性
	SPI_InitStruct.SPI_CRCPolynomial = 7;  //CRC:未用,赋一个默认值
	SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;  //数据帧大小:8位
	SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //双线双向全双工
	SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;  //高位先行
	SPI_InitStruct.SPI_Mode = SPI_Mode_Master;  //主机
	SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
	SPI_Init(SPI1,&SPI_InitStruct);

(4)使能SPI外设