STM32通信模拟SPI

一.SPI 协议
SPI(Serial Peripheral Interface,串行外设接口)是由摩托罗拉(Motorola)在1980前后提出的一种全双工同步串行通信接口,它用于MCU与各种外围设备以串行方式进行通信以交换信息,通信速度最高可达25MHz以上。

SPI接口主要应用在EEPROM、FLASH、实时时钟、网络控制器、OLED显示驱动器、AD转换器,数字信号处理器、数字信号解码器等设备之间。

SPI通常由四条线组成,一条主设备输出与从设备输入(Master Output Slave Input,MOSI),一条主设备输入与从设备输出(Master Input Slave Output,MISO),一条时钟信号(Serial Clock,SCLK),一条从设备使能选择(Chip Select,CS)。与I²C类似,协议都比较简单,也可以使用GPIO模拟SPI时序。

SPI和I²C对比如表 21.1.1 所示。SPI可以同时发出和接收数据,因此SPI的理论传输速度比I²C更快。SPI通过片选引脚选择从机,一个片选一个从机,因此在多从机结构中,需要占用较多引脚,而I²C通过设备地址选择从机,只要设备地址不冲突,始终只需要两个引脚。
STM32通信模拟SPI_第1张图片
物理拓扑结构

SPI可以一个主机连接单个或多个从机,每个从机都使用一个引脚进行片选,物理连接示意图如图21.1.1 和 图 21.1.2 所示。
STM32通信模拟SPI_第2张图片
数据交换

在SCK时钟周期的驱动下,MOSI和MISO同时进行,如图 21.1.3 所示,可以看作一个虚拟的环形拓扑结构。
STM32通信模拟SPI_第3张图片
主机和从机都有一个移位寄存器,主机移位寄存器数据经过MOSI将数据写入从机的移位寄存器,此时从机移位寄存器的数据也通过MISO传给了主机,实现了两个移位寄存器的数据交换。无论主机还是从机,发送和接收都是同时进行的,如同一个“环”。

如果主机只对从机进行写操作,主机只需忽略接收的从机数据即可。如果主机要读取从机数据,需要主机发送一个空字节(0xff)来引发从机发送数据。

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

传输模式
SPI有四种传输模式,如表 21.1.2 所示,主要差别在于CPOL和CPHA的不同。

CPOL(Clock Polarity,时钟极性)表示SCK在空闲时为高电平还是低电平。当CPOL=0,SCK空闲时为低电平,当CPOL=1,SCK空闲时为高电平。

CPHA(Clock Phase,时钟相位)表示SCK在第几个时钟边缘采样数据。当CPHA=0,在SCK第一个边沿采样数据,当CPHA=1,在SCK第二个边沿采样数据。
STM32通信模拟SPI_第4张图片
如图 21.1.4 所示,CPHA=0时,表示在时钟第一个时钟边沿采样数据。当CPOL=1,即空闲时为高电平,从高电平变为低电平,第一个时钟边沿(下降沿)即进行采样。当CPOL=0,即空闲时为低电平,从低电平变为高电平,第一个时钟边沿(上升沿)即进行采样。
STM32通信模拟SPI_第5张图片
如图 21.1.5 所示,CPHA=1时,表示在时钟第二个时钟边沿采样数据。当CPOL=1,即空闲时为高电平,从高电平变为低电平再变为高电平,第二个时钟边沿(上升沿)即进行采样。当CPOL=0,即空闲时为低电平,从低电平变为高电平再变为低电平,第二个时钟边沿(下降沿)即进行采样。
STM32通信模拟SPI_第6张图片
在这里插入图片描述
STM32通信模拟SPI_第7张图片
STM32通信模拟SPI_第8张图片
STM32通信模拟SPI_第9张图片
STM32通信模拟SPI_第10张图片

有了以上基础知识,基本可以想象出如何使用GPIO模拟SPI通信时序。首先主机和从机都选择同一传输模式。然后主机片选拉低,选中从机。接着在时钟的驱动下,MOSI发送数据,同时MISO读取接收数据。最后完成传输,取消片选。

二.FLASH 介绍
关于Flash,前面EEPROM章节,有过简单介绍。EEPROM和Flash的本质上是一样的,都用于保存数据,Flash包括MCU内部的Flash和外部扩展的Flash,本开发板的W25Q64就是一颗SPI接口的外部Flash。从功能上,Flash通常存放运行代码,运行过程中不会修改,而EEPROM存放用户数据,可能会反复修改。从结构上,Flash按扇区操作,EEPROM通常按字节操作。

结构组成

Flash类型众多,其中比较常见是W25Qxx系列,从命名上看,W25Qxx中xx的单位是M Bit,本开发板上的Flash型号为W25Q64,其存储容量为64M Bit。

对于W25Q64,每页大小为256 Byte。如图 21.1.6 所示,W25Q64由128块(Block)组成,每块由16扇 区(Sector)组成,W25Qxx的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。这样我们需要给W25Qxx开辟一个至少4K的缓存区,这样对SRAM要求比较高,要求芯片必须有4K以上SRAM才能很好的操作。每个扇区由16页(Page)组成,每一页由256个字节(Byte)组成,每个Byte由8位(Bit)组成,Bit为最小存储单位,存放1个0或1。

Flash有个物理特性:只能写0,不能写1。如果把Flash的每个Bit,都看作一张纸,bit=1表示纸没有内容,bit=0表示纸写入了内容。当纸为白纸时(bit=1),这时往纸上写东西是可以的,写完后纸的状态变为bit=0。当纸有内容时(bit=0),这时往纸上写东西只能让数据越乱,也就无法正常写数据。此时需要橡皮檫,进行擦除操作,将有内容的纸(bit=0)变为白纸(bit=1),使得以后可以重新写入数据。

因此,对Flash写数据前,通常需要擦除操作。对于W25Q64,数据擦除可以以Sector为单位也可以以Block为单位。数据写入只能按照Page来写入,也就一次最多只能写256个Byte。
STM32通信模拟SPI_第11张图片
SPI相关库函数:

void SPI_I2S_DeInit(SPI_TypeDef* SPIx);
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

程序配置过程:

①配置相关引脚的复用功能,使能SPIx时钟
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
②初始化SPIx,设置SPIx工作模式
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
③使能SPIx
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
④SPI传输数据
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;
⑤查看SPI传输状态
SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)

你可能感兴趣的:(笔记,嵌入式)