1.SPI的概念
SPI是串行外围设备接口,是一种高速全双工设备接口,(全双工是一根线收数据,一根线发数据,半双工是一根线同时收发数据)
SPI通过四条线与主机相连,分别是SS(从机选择线)MISO(主设备输入,从设备输出线)MOSI(主设备输出,从设备输出线)SCK(时钟信号线)
1.SS:片选信号线,每一个从设备只有一条SS信号线与主机相连,
有多少从设备,就有多少SS信号线,
SS低电平,设备被选中,开始通讯
SS高电平,设备不被选中,通讯结束
2。MISO:主设备输入,从设备输出信号线
主机从这条信号线读入数据,从机从这条信号线发送数据
3.MOSI:主设备输出,从设备输入
主机的数据从这条信号线发送数据,从机从这条信号线读数据
4.SCK:时钟信号线,用于通讯数据同步,由主机设置通讯速率,通讯速率要小于从设备最高速率
STM32F10X有3个SPI接口,SPI1挂APB2上,速率最高36Mbit/s,SPI2和SPI3挂在APB1上,速率最高18Mbi/s
2.SPI通讯
上图是SPI通讯过程
1.SS由高到低表示通讯开始,SS由低到高表示通讯结束,SCK时钟线进行数据同步,使用MSB先行模式,在SCK上升沿变化输出,SCK下降沿采集数据。
2.SPI的4种通讯模式
SPI的4种工作模式,主要区别在于总线空闲时SCK的时钟状态以及采样时刻
工作模式1:CPOL=0,CPHA=0,空闲时SCK时钟为低电平,在SCK的奇数边沿被采样
工作模式2:CPOL=0, CPHA=1,空闲时SCK时钟为低电平,在SCK的偶数边沿被采样
工作模式3:CPOL=1,CPHA=0,空闲时SCK时钟为高电平,在SCK的奇数边沿被采样
工作模式4:CPOL=1,CPHA=1,空闲时SCK时钟为高电平,在SCK的偶数边沿被采样
SPI的模式配置:
GPIO口除了SS信号线外都配置成复用推挽输出。
- SPI_Direction
设置SPI的通讯方向,四种
SPI_Direction_2Lines_FullDuplex SPI设置为双线双向全双工
SPI_Direction_2Lines_RxOnly SPI设置为双线单向接收
SPI_Direction_1Line_Rx SPI设置为单线双向接收
SPI_Direction_1Line_Tx SPI设置为单线双向发送 - SPI_Mode
SPI的主从模式,MCU做主机发送SCK时钟,配置为主机模式
SPI_Mode_Master 设置为主SPI
SPI_Mode_Slave 设置为从SPI - SPI_DataSize
SPI_DataSize_16b SPI发送接收16位帧结构
SPI_DataSize_8b SPI发送接收8位帧结构 - SPI_CPOL和SPI_CPHA
时钟极性和时钟相位,决定SPI的四种工作模式
SPI_CPOL_High 时钟悬空高
SPI_CPOL_Low 时钟悬空低
SPI_CPHA_2Edge 数据捕获于第二个时钟沿
SPI_CPHA_1Edge 数据捕获于第一个时钟沿 - SPI_NSS
配置NSS模式,有硬件模式与软件模式,一般用软件模式
SPI_NSS_Hard SPI_NSS_Soft - SPI_BaudRatePrescaler
设置SCK时钟频率,可设置为fpclk 的2、4、6、8、16、32、64、128、256 分频 - SPI_FirstBit
MSB 先行(高位数据在前)还是LSB 先行(低位数据在前) - SPI_CRCPolynomial
用于CRC值计算的多项式
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_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
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(FLASH_SPIx , &SPI_InitStructure);
利用SPI发送一个字节
通讯过程如下:
9. SS信号线置低电平
10. 等待SPI的状态寄存器SR的TXE标志位置1,表示发送缓冲区为空,此时才可以继续发送SPI数据
11. 发送一个字节
12. 等待SPI的RXNE标志位为1,表示接收缓冲区非空,此时才可以接收数据
13. 读取SPI缓冲区的数据
u8 SPI_FLASH_SendByte(u8 byte)
{
SPITimeout = SPIT_FLAG_TIMEOUT; //1000
/* 等待发送缓冲区为空,TXE事件 */
while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0); //读错误
}
/* 写入数据寄存器,把要写入的数据写入发送缓冲区 */
SPI_I2S_SendData(FLASH_SPIx , byte);
SPITimeout = SPIT_FLAG_TIMEOUT; //1000
/* 等待接收缓冲区非空,RXNE事件 */
while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_RXNE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1);
}
/* 读取数据寄存器,获取接收缓冲区数据 */
return SPI_I2S_ReceiveData(FLASH_SPIx ); //SPI1
}