SPI通信

SPI即串行外围设备接口,是全双工的通信总线,有四根线

M:主设备 S:从设备 I:输入 O:输出

MISO:主设备数据输入,从设备数据输出

MOSI:主设备数据输出,从设备数据输入

SCLK:时钟信号,由主设备产生

CS:从设备片选信号,由主设备控制

工作原理:

1)主机和丛集都有一个串行移位寄存器,主机通过他的SPI串行寄存器写入一个字节发起一次传输。

2)串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过MISO信号线返回给主机,这样,两个移位寄存器的内容就被交换。

3)外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,如主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

状态标志:

TXE(发送缓冲器空闲标志):

  TXE=1表明发送缓冲器为空,可以写下一个待发送的数据进入缓冲器中,当写入SPI_DR时,TXE标志被清零。

RXNE(接收缓冲器非空):

  RXNE=1表明在接收缓冲器中包含有效的接收数据。读SPI数据寄存器可以清楚此标志。

BUSY(忙标志):

  busy标志由硬件设置与清楚(写入此位无效果)

程序配置过程:(来源于战舰STM32F1库函数版本)

1) 配置相关引脚的复用功能,使能 SPI2 时钟
我们要用 SPI2,第一步就要使能 SPI2 的时钟。其次要设置 SPI2 的相关引脚为复用输出,
这样才会连接到 SPI2 上否则这些 IO 口还是默认的状态,也就是标准输入输出口。这里我们使
用的是 PB13、 14、 15 这 3 个(SCK.、 MISO、 MOSI, CS 使用软件管理方式),所以设置这三
个为复用 IO。
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//PORTB 时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE );//SPI2 时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 GPIOB
类似的时钟使能和 IO 初始化我们前面多次讲解到,这里不做详细介绍。
2) 初始化 SPI2,设置 SPI2 工作模式
接下来我们要初始化 SPI2,设置 SPI2 为主机模式,设置数据格式为 8 位,然设置 SCK 时钟

极性及采样方式。并设置 SPI2 的时钟频率(最大 18Mhz),以及数据的格式(MSB 在前还是
LSB 在前)。 这在库函数中是通过 SPI_Init 函数来实现的。
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
跟其他外设初始化一样,第一个参数是 SPI 标号,这里我们是使用的 SPI2。 下面我们来看看第
二个参数结构体类型 SPI_InitTypeDef 的定义:
typedef struct
{
uint16_t SPI_Direction;
uint16_t SPI_Mode;
uint16_t SPI_DataSize;
uint16_t SPI_CPOL;
uint16_t SPI_CPHA;
uint16_t SPI_NSS;
uint16_t SPI_BaudRatePrescaler;
uint16_t SPI_FirstBit;
uint16_t SPI_CRCPolynomial;
}SPI_InitTypeDef;
结构体成员变量比较多,这里我们挑取几个重要的成员变量讲解一下:
第一个参数 SPI_Direction 是用来设置 SPI 的通信方式, 可以选择为半双工,全双工,以及串行
发和串行收方式, 这里我们选择全双工模式 SPI_Direction_2Lines_FullDuplex。
第二个参数 SPI_Mode 用来设置 SPI 的主从模式,这里我们设置为主机模式 SPI_Mode_Master,
当然有需要你也可以选择为从机模式 SPI_Mode_Slave。
第三个参数 SPI_DataSiz 为 8 位还是 16 位帧格式选择项,这里我们是 8 位传输,选择
SPI_DataSize_8b。
第四个参数 SPI_CPOL 用来设置时钟极性, 我们设置串行同步时钟的空闲状态为高电平所以我
们选择 SPI_CPOL_High。
第五个参数 SPI_CPHA 用来设置时钟相位, 也就是选择在串行同步时钟的第几个跳变沿(上升
或下降)数据被采样, 可以为第一个或者第二个条边沿采集, 这里我们选择第二个跳变沿,所
以选择 SPI_CPHA_2Edge
第六个参数 SPI_NSS 设置 NSS 信号由硬件(NSS 管脚)还是软件控制,这里我们通过软件控
制 NSS 关键,而不是硬件自动控制,所以选择 SPI_NSS_Soft。
第七个参数 SPI_BaudRatePrescaler 很关键,就是设置 SPI 波特率预分频值也就是决定 SPI 的时
钟的参数, 从不分频道 256 分频 8 个可选值 ,初始化的时候我们选择 256 分频值
SPI_BaudRatePrescaler_256, 传输速度为 36M/256=140.625KHz。
第八个参数 SPI_FirstBit 设置数据传输顺序是 MSB 位在前还是 LSB 位在前, ,这里我们选择
SPI_FirstBit_MSB 高位在前。
第九个参数 SPI_CRCPolynomial 是用来设置 CRC 校验多项式, 提高通信可靠性, 大于 1 即可。
设置好上面 9 个参数,我们就可以初始化 SPI 外设了。 初始化的范例格式为:
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主 SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI 发送接收 8 位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//串行同步时钟的空闲状态为高电平

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//第二个跳变沿数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信号由软件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //预分频 256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从 MSB 位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); //根据指定的参数初始化外设 SPIx 寄存器
3) 使能 SPI2
初始化完成之后接下来是要使能 SPI2 通信了, 在使能 SPI2 之后,我们就可以开始 SPI 通
讯了。 使能 SPI2 的方法是:
SPI_Cmd(SPI2, ENABLE); //使能 SPI 外设
4) SPI 传输数据
通信接口当然需要有发送数据和接受数据的函数,固件库提供的发送数据函数原型为:
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
这个函数很好理解,往 SPIx 数据寄存器写入数据 Data,从而实现发送。
固件库提供的接受数据函数原型为:
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;
这个函数也不难理解,从 SPIx 数据寄存器读出接受到的数据。
5) 查看 SPI 传输状态
在 SPI 传输过程中,我们经常要判断数据是否传输完成,发送区是否为空等等状态,这是
通过函数 SPI_I2S_GetFlagStatus 实现的,这个函数很简单就不详细讲解,判断发送是否完成的
方法是:
SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);
SPI2 的使用就介绍到这里,接下来介绍一下 W25Q128。 W25Q128 是华邦公司推出的大容
量 SPI FLASH 产品, W25Q128 的容量为 128Mb, 该系列还有 W25Q80/16/32/64 等。 ALIENTEK
所选择的 W25Q128 容量为 128Mb,也就是 16M 字节。
W25Q128 将 16M 的容量分为 256 个块(Block),每个块大小为 64K 字节,每个块又分为
16 个扇区(Sector),每个扇区 4K 个字节。 W25Q128 的最小擦除单位为一个扇区,也就是每次
必须擦除 4K 个字节。这样我们需要给 W25Q128 开辟一个至少 4K 的缓存区,这样对 SRAM 要
求比较高,要求芯片必须有 4K 以上 SRAM 才能很好的操作。
W25Q128 的擦写周期多达 10W 次,具有 20 年的数据保存期限,支持电压为 2.7~3.6V,
W25Q128 支持标准的 SPI,还支持双输出/四输出的 SPI,最大 SPI 时钟可以到 80Mhz(双输出
时相当于 160Mhz,四输出时相当于 320M),更多的 W25Q128 的介绍,请参考 W25Q128 的
DATASHEET。

你可能感兴趣的:(SPI通信)