一、SPI初始化结构体定义
SPI_InitTypeDef SPI_InitStructure;
二、SPI初始化结构体的标准库定义
typedef struct
{
uint16_t SPI_Direction; /*!< Specifies the SPI unidirectional or bidirectional data mode.
This parameter can be a value of @ref SPI_data_direction */
uint16_t SPI_Mode; /*!< Specifies the SPI operating mode.
This parameter can be a value of @ref SPI_mode */
uint16_t SPI_DataSize; /*!< Specifies the SPI data size.
This parameter can be a value of @ref SPI_data_size */
uint16_t SPI_CPOL; /*!< Specifies the serial clock steady state.
This parameter can be a value of @ref SPI_Clock_Polarity */
uint16_t SPI_CPHA; /*!< Specifies the clock active edge for the bit capture.
This parameter can be a value of @ref SPI_Clock_Phase */
uint16_t SPI_NSS; /*!< Specifies whether the NSS signal is managed by
hardware (NSS pin) or by software using the SSI bit.
This parameter can be a value of @ref SPI_Slave_Select_management */
uint16_t SPI_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be
used to configure the transmit and receive SCK clock.
This parameter can be a value of @ref SPI_BaudRate_Prescaler.
@note The communication clock is derived from the master
clock. The slave clock does not need to be set. */
uint16_t SPI_FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit.
This parameter can be a value of @ref SPI_MSB_LSB_transmission */
uint16_t SPI_CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. */
}SPI_InitTypeDef;
在定义处我们可以看到注释如下
图1、库函数定义处注释
双击划线部分可以跳转(双击选中,按下Ctrl + F,点击Find Next )到可填入参数的定义处;
三、参数讲解
1、SPI_Direction参数
图2、SPI_Direction可填入参数定义定义
这个参数是设置硬件SPI数据传输方向的,可填入的参数如下:
SPI_Direction_2Lines_FullDuplex、SPI_Direction_2Lines_RxOnly、SPI_Direction_1Line_Rx、SPI_Direction_1Line_Tx;
(1) SPI_Direction_2Lines_FullDuplex
设置SPI为双线双向全双工模式。在这种模式下,SPI可以同时进行数据的发送和接收,这是最常见的SPI通信模式,适用于大多数应用场景。
(2) SPI_Direction_2Lines_RxOnly
设置SPI为双线单向接收模式。在这种模式下,SPI只接收数据,不发送数据,适用于多从设备模式,当设备未被访问时,可以处于这种模式,避免总线上的数据冲突。
(3) SPI_Direction_1Line_Rx
设置SPI为单线双向接收模式。这种模式使用三线制,只接收数据,适用于某些特定的应用场景,如某些类型的传感器或显示器。
(4) SPI_Direction_1Line_Tx
设置SPI为单线双向发送模式。这种模式也使用三线制,只发送数据,与SPI_Direction_1Line_Rx一起组成“单线双向”模式,适用于需要单向数据流的应用
2、SPI_Mode参数
图2、SPI_Mode可填入参数定义定义
这个参数是设置硬件SPI工作模式的,可填入的参数如下:SPI_Mode_Master、SPI_Mode_Slave。
(1)SPI_Mode_Master
设置SPI为主机模式。在这种模式下,SPI的SCK信号线的时序是由通讯中的主机产生的。作为主机,STM32的SPI外设将产生时钟信号,并控制数据的发送和接收过程。
(2)SPI_Mode_Slave
设置SPI为从机模式。在这种模式下,STM32的SPI外设将接受外来的SCK信号。从机模式的SPI不会产生时钟信号,而是根据主机的时钟信号来同步数据的发送和接收。
3、SPI_DataSize参数
图2、SPI_DataSize可填入参数定义定义
这个参数是设置SPI数据帧大小的,它决定了每次SPI传输中数据的位数。可填入的参数如下:
SPI_DataSize_16b、SPI_DataSize_8b。
(1)SPI_DataSize_16b
设置SPI数据帧大小为16位。这是最常见的数据帧大小,适用于大多数应用场景。
(2)SPI_DataSize_8b
设置SPI数据帧大小为8位。这种配置适用于需要较小数据帧大小的应用。
4、SPI_CPOL参数
图2、SPI_CPOL可填入参数定义定义
SPI_CPOL
(Clock Polarity,时钟极性)是一个关键的配置参数,它决定了SPI总线在空闲状态时时钟线(SCK)的电平。它可以填入的参数如下:SPI_CPOL_Low、SPI_CPOL_High。
(1)SPI_CPOL_Low
设置时钟线在空闲状态时为低电平。这意味着在没有数据传输时,时钟线是低电平的。
(2)SPI_CPOL_High
设置时钟线在空闲状态时为高电平。这意味着在没有数据传输时,时钟线是高电平的。
5、SPI_CPHA参数
图2、SPI_CPHA可填入参数定义定义
SPI_CPHA
(Clock Phase,时钟相位)是一个关键的配置参数,它决定了数据在时钟信号的哪个边沿被采样。他可填入的参数如下:SPI_CPHA_1Edge、SPI_CPHA_2Edge.
(1)SPI_CPHA_1Edge
设置数据在时钟信号的第一个边沿(上升沿)被采样。这意味着数据在时钟信号从低电平跳变到高电平时被采样。
(2)SPI_CPHA_2Edge
设置数据在时钟信号的第二个边沿(下降沿)被采样。这意味着数据在时钟信号从高电平跳变到低电平时被采样。
SPI_CPHA
的设置与SPI_CPOL
(Clock Polarity,时钟极性)一起决定了SPI通信的四种模式,这些模式包括:
- MODE0:
SPI_CPOL
= 0,SPI_CPHA
= 0 - MODE1:
SPI_CPOL
= 0,SPI_CPHA
= 1 - MODE2:
SPI_CPOL
= 1,SPI_CPHA
= 0 - MODE3:
SPI_CPOL
= 1,SPI_CPHA
= 1 - 每种模式都有其特定的时钟信号行为,这些行为决定了数据在时钟信号的哪个边沿被采样。例如,在MODE0中,数据在时钟信号的第一个边沿(上升沿)被采样,而在MODE3中,数据在时钟信号的第二个边沿(下降沿)被采样。
6、SPI_NSS参数
图2、SPI_NSS可填入参数定义定义
SPI_NSS
(Slave Select,从设备选择)是一个用于控制从设备选择信号的参数。它决定了SPI通信中的从设备选择信号(NSS)是硬件自动控制还是由软件控制。它填入的参数如下:SPI_NSS_Hard、SPI_NSS_Soft。
(1)SPI_NSS_Hard
硬件NSS模式。在这种模式下,NSS信号由硬件自动产生,通常用于只有一个从设备的简单SPI网络。在硬件NSS模式下,NSS信号在数据传输期间自动拉低,以选中从设备进行通信。
(2)SPI_NSS_Soft
软件NSS模式。在这种模式下,NSS信号由软件控制,通常通过一个GPIO引脚来实现。软件NSS模式允许SPI接口连接多个从设备,因为NSS信号可以独立地为每个从设备控制。在软件NSS模式下,开发者需要通过编程来控制GPIO引脚的电平,以手动选择要通信的从设备
7、SPI_BaudRatePrescaler参数
图2、SPI_BaudRatePrescaler可填入参数定义定义
SPI_BaudRatePrescaler
(波特率预分频器)是一个用于设置SPI通信速率的参数。它通过预分频器对时钟频率进行分频,从而控制SPI的通信速率。它可填入的参数如下:SPI_BaudRatePrescaler_2、SPI_BaudRatePrescaler_4、SPI_BaudRatePrescaler_8、SPI_BaudRatePrescaler_16、SPI_BaudRatePrescaler_32、SPI_BaudRatePrescaler_64、SPI_BaudRatePrescaler_128、SPI_BaudRatePrescaler_256。
(1)SPI_BaudRatePrescaler_2
选择本参数后,SPI通信速率为72MHz / 2= 36MHz
(2)SPI_BaudRatePrescaler_4
选择本参数后,SPI通信速率为72MHz / 4= 18MHz
(3)SPI_BaudRatePrescaler_8
选择本参数后,SPI通信速率为72MHz / 8= 9MHz
(4)SPI_BaudRatePrescaler_16
选择本参数后,SPI通信速率为72MHz / 16= 4.5MHz
(5)SPI_BaudRatePrescaler_32
选择本参数后,SPI通信速率为72MHz / 32= 2.25MHz
(6)SPI_BaudRatePrescaler_64
选择本参数后,SPI通信速率为72MHz / 64= 1.125MHz
(7)SPI_BaudRatePrescaler_128
选择本参数后,SPI通信速率为72MHz / 128= 0.5625MHz
(8)SPI_BaudRatePrescaler_256
选择本参数后,SPI通信速率为72MHz / 256= 0.28125MHz
根据实际需求选择波特率预分频器的填入参数,选择更符合实际情况的通信速率。
8、SPI_FirstBit参数
图2、SPI_FirstBit可填入参数定义定义
SPI_FirstBit
参数用于设置数据传输时的位顺序,即决定了数据的哪个位首先被传输。它可填入的参数如下:SPI_FirstBit_MSB、SPI_FirstBit_LSB。
(1)SPI_FirstBit_MSB
设置为最高有效位(MSB)首先传输。这是最常见的设置,意味着在数据传输时,最高有效位(即数据字节的最高位)会首先被发送出去,也就是从左到右的顺序。
(2)SPI_FirstBit_LSB
设置为最低有效位(LSB)首先传输。这种设置不常用,但在某些特定的通信协议或设备中可能会要求使用最低有效位首先传输,也就是从右到左的顺序。
9、SPI_CRCPolynomial参数
SPI_CRCPolynomial
参数用于设置用于CRC(循环冗余校验)值计算的多项式。CRC是一种用于检测数据传输过程中错误的校验算法。在SPI通信中,可以通过配置SPI_CRCPolynomial
参数来指定CRC校验的多项式。
例如,可以将SPI_CRCPolynomial
设置为7,这样配置后,SPI模块在进行数据传输时,会使用多项式为7的CRC算法进行校验。具体的CRC算法实现会根据硬件设备的不同而有所差异。需要注意的是,SPI_CRCPolynomial
的取值范围通常是0到255之间的整数,具体取值根据硬件设备的要求而定。
在STM32的SPI配置中,CRC的计算是通过设置SPI_CR1
寄存器中的CRCEN
位启用的。设置CRCEN
位时同时复位CRC寄存器(SPI_RXCRCR
和SPI_TXCRCR
)。当设置了SPI_CR1
的CRCNEXT
位,SPI_TXCRCR
的内容将在当前字节发送之后发出。一个数据字节发送完成后,发送CRC。在发送CRC期间,CRC计算停止;当最后一个字节或半字被发送后,SPI发送CRC,CRCNext
位被清除。同样,接收到的CRC和SPI_RXCRCR
值进行比较,如果比较不相配,SPI_SR
上的CRCERR
标志被置位。
在实际应用中,SPI_CRCPolynomial
的设置应与通信双方的设备要求相匹配,以确保数据的正确传输和校验。如果设备不支持CRC校验,那么这个参数的设置将不会影响通信,但通常建议保持与设备手册或数据表中的推荐设置一致。
四、SPI使能函数
SPI_Cmd是SPIx的使能函数,它可填入的参数有两个,即SPIx、NewState。
(1)SPIx
给本参数选择填入参数时,需要根据芯片型号查询给芯片系列所拥有的SPI个数即SPI的序号,如我需要给F103初始化,那我需要知道F103有几个SPI,是什么型号;假设F103有三个SPI,分别是SPI1、SPI2、 SPI3,即可填入的参数就是这三个。
(2)NewSate
本参数可选择的范围仅为 ENABLE / DISABLE ,填入ENABLE即可开启对应的SPIx,若是DISABLE,既不开启对应的SPIx。
五、代码初始化模版
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //开启SPI1的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA4引脚初始化为推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA5和PA7引脚初始化为复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA6引脚初始化为上拉输入
/*SPI初始化*/
SPI_InitTypeDef SPI_InitStructure; //定义结构体变量
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //模式,选择为SPI主模式
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //方向,选择2线全双工
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //数据宽度,选择为8位
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //先行位,选择高位先行
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; //波特率分频,选择128分频
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //SPI极性,选择低极性
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //SPI相位,选择第一个时钟边沿采样,极性和相位决定选择SPI模式0
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS,选择由软件控制
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC多项式,暂时用不到,给默认值7
SPI_Init(SPI1, &SPI_InitStructure); //将结构体变量交给SPI_Init,配置SPI1
/*SPI使能*/
SPI_Cmd(SPI1, ENABLE); //使能SPI1,开始运行
上述代码摘自B站UP “江协科技” 所分享 STM32F103C8t6 资料的SPI初始化源码
该课程连接:STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili
视频链接中的视频简介有资料的下载方式。