基于ARM开发板从零开始学习STM32 07-SPI通信协议

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/huolu0602/article/details/102748110

SPI 协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。广泛地应用在 ADC、LCD 等设备与 MCU 间通讯的场合。

SPI信号线

SPI 总线包含 4 条总线,分别为NSS,SCK、MOSI、MISO。它们的作用介绍如下:

  1. NSS:片选信号线,当有多个 SPI 设备与MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其它的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,当NSS信号线为低电平时,片选有效,开始 SPI 通讯。
  2. SCK:时钟信号线,由主通讯设备产生,不同的设备支持的时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 f pclk /2。
  3. MOSI:主设备输出/从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入数据,即这条线上数据的方向为主机到从机。
  4. MISO:主设备输入/从设备输出引脚。主机从这条信号线读入数据,从机的数据则由这条信号线输出,即在这条线上数据的方向为从机到主机。

    SPI  模式

    根据 SPI 时钟极性(CPOL)和时钟相位(CPHA) 配置的不同,分为四种 SPI 模式。

    时钟极性是指 SPI 通讯设备处于空闲状态时(也可以认为这是 SPI 通讯开始时,即NSS线为低电平时),SCK 信号线的电平信号。CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时,则相反。

    时钟相位是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的奇数边沿被采样。当 CPHA=1 时,数据线在 SCK的偶数边沿采样。

    STM32 的 SPI特性

    单次传输可选择为 8 或 16 位。

    波特率预分频系数(最大为 f PCLK /2) 。

    时钟极性(CPOL)和相位(CPHA)可编程设置 。

    数据顺序的传输顺序可进行编程选择,MSB 在前或 LSB 在前 。

    可触发中断的专用发送和接收标志。

    可以使用 DMA 进行数据传输操作。

    STM32的SPI架构分析

                  

可以看到 MISO 数据线接收到的信号经移位寄存器处理后把数据转移到接收缓冲区,然后这个数据就可以由我们的软件从接收缓冲区读出了。当要发送数据时,我们把数据写入到发送缓冲区,硬件将会把它用移位寄存器处理后输出到 MOSI 数据线。

SCK 的时钟信号则由波特率发生器产生,我们可以通过波特率控制位(BR)来控制它输出的波特率。

控制寄存器 CR1 掌管着主控制电路,STM32 的 SPI 模块的协议设置(时钟极性、相位等)就是由它来制定的。而控制寄存器 CR2 则用于设置各种中断使能。

最后的为 NSS 引脚,NSS片选信号线的角色,如果我们把 NSS 引脚配置为硬件自动控制,SPI 模块能够自动判别它能否成为 SPI 的主机,或自动进入 SPI 从机模式。但实际上我们用得更多的是由软件控制某些 GPIO 引脚单独作为NSS信号,这个 GPIO 引脚可以随便选择。

SPI接口读取 FLASH实例分析

首先,SPI初始化。SPI_FLASH_Init()函数初始化了 SPI1 复用到的 GPIO 引脚,启动了 GPIO及 SPI1 外设的时钟,并初始化了 SPI 的模式。

void SPI1_Init(void)
{
	SPI_InitTypeDef SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | 
    RCC_APB2Periph_SPI1,ENABLE);

	GPIO_InitStructure.GPIO_Pin = SpiFlash_nCs;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOC,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = SpiFlash_CLK | SpiFlash_MOSI;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = SpiFlash_MISO;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial = 7;
	SPI_Init(SPI1,&SPI_InitStructure);

	SPI_Cmd(SPI1,ENABLE);
}

对spi的配置很简单,重要的是理解整个通信的过程。

下图是SPI的GPIO引脚复用设置:

                     

SPI模式初始化

(1) SPI_Mode

STM32 的 SPI 设备可以工作在主机模式(SPI_Mode_Master)或从机模式(SPI_Mode_Slave ),这两个模式的最大区别为 SPI 的 SCK 信号线的时序,SCK 的时序是由通讯中的主机产生的。若被配置为从机模式,STM32 的 SPI 模块将接受外来的 SCK 信号。

 (2) SPI_DataSize

这个成员可以选择 SPI 每次通讯的数据大小(称为数据帧)为 8 位还是 16位。

 (3) SPI_CPOL 和 SPI_CPHA

这两个成员就是配置 SPI 的时钟极性(CPOL)和时钟相位(CPHA),这两个配置影响到 SPI 的通讯模式,要设置成符合将要互相通讯的设备的要求。CPOL 分别可以取 SPI_CPOL_High(SPI 通讯空闲时 SCK 为高电平)和SPI_CPOL_Low(SPI 通讯空闲时 SCK 为低电平) 。CPHA 则可以取 SPI_CPHA_1Edge(在 SCK 的奇数边沿采集数据) 和SPI_CPHA_2Edge (在 SCK 的偶数边沿采集数据)。

(4) SPI_NSS

本成员配置 NSS 引脚的使用模式,可以选择为硬件模式(SPI_NSS_Hard )与软件模式(SPI_NSS_Soft ),在硬件模式中的 SPI 片选信号由硬件自动产生,而软件模式则需要我们亲自把相应的 GPIO 端口拉高或置低产生非片选和片选信号。如果外界条件允许,硬件模式还会自动将 STM32 的 SPI 设置为主机。

 (5) SPI_BaudRatePrescaler

本成员设置波特率分频值,分频后的时钟即为 SPI 的 SCK 信号线的时钟频率。这个成员参数可设置为 fpclk 的 2、4、6、8、16、32、64、128、256 分频。

(6) SPI_FirstBit

所有串行的通讯协议都会有 MSB 先行(高位数据在前)还是 LSB 先行(低位数据在前)的问题,而 STM32 的 SPI 模块可以通过这个结构体成员,对这个特性编程控制。

(7) SPI_CRCPolynomial

这是 SPI 的 CRC 校验中的多项式,若我们使用 CRC 校验时,就使用这个成员的参数(多项式),来计算 CRC 的值。

配置完这些结构体成员后,我们要调用 SPI_Init()函数把这些参数写入到寄存器中,实现 SPI 的初始化,然后调用 SPI_Cmd()来使能 SPI1 外设。

以上实验主要讲述SPI的配置以及通信实例,工程已上传至网盘,有需要的自行下载,链接:https://pan.baidu.com/s/1wfykkxyhZooELFWRcCM7Kw 
提取码:rswp。

猜你喜欢

转载自blog.csdn.net/huolu0602/article/details/102748110