1.SPI通信接口
一种全双工,同步的,一种通信接口。故至少有2根数据线,1根时钟线,但还有一根片选的线,主要应用在EEPPOM,FLASH,实时时钟,AD转换器等。
这里复习一下,IIC接口,同步半双工。
USART接口,异步全双工。
2.SPI接口原理
1.SPI框图
作为主机
MOSI接口为输出接口,地址和数据总线写入发送缓冲区,到移位寄存器,移出一位到MOSI,这时MISO接口就会输入一位数据到移位寄存器进行数据交互。
就是发送一个位时同时会接收一位
2.SPI框图
SPI接口一般使用4条线通信:
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK时钟信号,由主设备产生。
CS从设备片选信号,由主设备控制。
从机主机都有一个移位寄存器,用于一位一位数据的移动与填入
3.SPI工作原理
1.硬件上为4根线。
2.主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。
3.串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过MISO信号线返回给主机。这样,两个移位寄存器中的内容就被交换。
4.外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输
4.从器件引脚管理
SPI可以一个主机接入多个从机,如何确定与那个设备通信,有硬件管理和软件管理
软件管理
从器件选择信息在内部将SPI_CR1寄存器的SSI为的值驱动。外部NSS引脚空闲,可供其它应用使用。
就是SPI寄存器可以控制SPI是否工作。
硬件管理
就是SPI有一根片选择的线,想用就拉低,禁止就拉高。
5.时钟信号的相位与极性
SPI_CR寄存器的CPOI与CPHA,能够有四种组合。
CPHA为1时,
CPOL为1下,空闲状态为高电平
CPOL为0下,空闲状态为低电平
第二个边沿被采集
CPHA为0时,
CPOL为1下,空闲状态为高电平
CPOL为0下,空闲状态为低电平
第一个边沿被采集
主机与从设备这两个参数要匹配
6.数据发送接收格式
输出数据位可以控制高位在前或低位在前,可以控制数据一帧为8位或16位
7.状态标志
发送缓冲器空闲标志TXE
为1时表示发送缓冲器为空,可以写入。写入后置0。
接收缓冲器非空RXNE
为1时表示接收缓冲有数据,可以读出来。读出后置0
忙标志Busy
标志现在是否在通信
8.SPI寄存器
SPI控制寄存器1(SPI_CR1)
SPI控制寄存器2(SPI_CR2)
SPI状态寄存器(SPI_SR)
SPI数据寄存器(SPI_DR)
SPI_I2S配置寄存器(SPI_I2S_CFGR)
SPI_I2S预分频寄存器(SPI_I2SPR)
3.SPI的HAL相关函数
1.初始化函数
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi);
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi);
SPI_HandleTypeDef *hspi,主要有用的为instan与Init初始化参数结构体
2.SPI发送与接收函数
3.SPI中断函数
4.SPI设置速度函数(波特率)
4.SPI的HAL设置步骤
5.SPI的HAL库函数代码
#include"spi.h"
SPI_HandleTypeDef spi5;
void Spi_Init()
{
spi5.Instance=SPI5;
spi5.Init.Mode = SPI_MODE_MASTER; //主模式
spi5.Init.Direction = SPI_DIRECTION_2LINES;//发送与接收
spi5.Init.DataSize = SPI_DATASIZE_8BIT; //8位数据格式
spi5.Init.CLKPolarity = SPI_POLARITY_HIGH; //极性,空闲状态为高电平
spi5.Init.CLKPhase = SPI_PHASE_2EDGE; //两个跳变沿读取数据
spi5.Init.NSS = SPI_NSS_SOFT; //选择为软件管理
spi5.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256; //波特率预分频
spi5.Init.FirstBit=SPI_FIRSTBIT_MSB; //高位首位
spi5.Init.TIMode=SPI_TIMODE_DISABLE; //TIMode不开启
spi5.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;;//关闭CRC校验
spi5.Init.CRCPolynomial=7; //CRC值计算的多项式,多少无所谓,已经关闭了
HAL_SPI_Init(&spi5);
__HAL_SPI_ENABLE(&spi5);
//SPI5_ReadWriteByte(0xff);
}
void SPI5_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
__HAL_SPI_DISABLE(&spi5); //关闭SPI
spi5.Instance->CR1&=0XFFC7; //位3-5清零,用来设置波特率
spi5.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
__HAL_SPI_ENABLE(&spi5); //使能SPI
}
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
__HAL_RCC_GPIOF_CLK_ENABLE(); //时钟使能
__HAL_RCC_SPI5_CLK_ENABLE();
GPIO_InitTypeDef GPIO_Initure;
if(hspi->Instance==SPI5)
{
GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速
GPIO_Initure.Alternate=GPIO_AF5_SPI5; //复用为USART1
HAL_GPIO_Init(GPIOF,&GPIO_Initure); //初始化PA9
}
}
u8 SPI5_ReadWriteByte(u8 TxDate)
{
u8 RxDate;
HAL_SPI_TransmitReceive(&spi5,&TxDate,&RxDate,sizeof(TxDate),1000);
//发送TxDate,存在Rxdate
return RxDate;
}
6.SPI的应用(W25QXX)
W25Q256是华邦公司生产的一颗容量为32M字节的串行FLASH芯片,它将32M的容量分为512个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Q256的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。这样我们需要给W25Q256开辟一个至少4K的缓存区,这样对SRAM要求比较高,要求芯片必须有4K以上SRAM才能很好的操作。
注:32M>分为16块>每块分为16个扇区(4K)
每次写入芯片时,先要根据地址找到扇区,然后将高扇区内容移到4k的缓存,才能写入数据,所以需要芯片有至少4k的缓存。
7.(W25QXX)引脚
8个引脚,输入输出引脚,片选,时钟,CVV,GND,
HOLD 保持断输入
WP 写保护
8.(W25QXX)指命
常用指命