您现在的位置是:首页 >学无止境 >STM32 硬件SPI读写W25Q64网站首页学无止境
STM32 硬件SPI读写W25Q64
简介STM32 硬件SPI读写W25Q64
接线图
函数介绍
写DR寄存器
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
读DR数据寄存器
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);
NSS引脚配置
void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);
8/16位数据帧配置
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);
功能函数
//写SS函数
void My_W_SS(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}
代码配置
1.定义结构体变量
定义GPIO与SPI外设的结构体变量
//定义结构体变量
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体变量
SPI_InitTypeDef SPI_InitStructure; //定义SPI外设结构体变量
2.开启时钟
开启SPI与GPIO A族的时钟
//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开GPIO A族的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //打开SPI外设时钟
3.初始化GPIO
SCK、MOSI是由硬件控制的输出信号所以配置位复用推挽输出,MISO是硬件控制的输入信号,配置为上拉输入,SS引脚是软件控制的,所以可以配置位通用推挽输出
//配置GPIO
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); //GPIO初始化
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); //GPIO初始化
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); //GPIO初始化
4.配置SPI外设
使用结构体配置
8/16位数据帧
高位先行/低位先行
SPI模式几
主机还是从机等
//配置SPI外设
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI模式,配置当前设备是主机还是从机
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//配置SPI裁剪引脚 配置为双线全双工
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//配置8/16数据帧 8位数据帧
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//配置高位先行还是低位先行 高位先行
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;//配置SCK时钟的频率
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟极性 空闲默认低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟相位 选择SPI模式0 CPHA = 0
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //选择软件NSS模式
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC校验多项式 默认值7
SPI_Init(SPI1, &SPI_InitStructure);
5.开关控制,开启SPI
//开启SPI外设
SPI_Cmd(SPI1, ENABLE);
整体代码
void MySPI_Init2(void)
{
//定义结构体变量
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体变量
SPI_InitTypeDef SPI_InitStructure; //定义SPI外设结构体变量
//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开GPIO A族的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //打开SPI外设时钟
//配置GPIO
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);//GPIO初始化
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);//GPIO初始化
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);//GPIO初始化
//配置SPI外设
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI模式,配置当前设备是主机还是从机
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//配置SPI裁剪引脚 配置为双线全双工
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//配置8/16数据帧 8位数据帧
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//配置高位先行还是低位先行 高位先行
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;//配置SCK时钟的频率
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//时钟极性 空闲默认低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//时钟相位 选择SPI模式0 CPHA = 0
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //选择软件NSS模式
SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC校验多项式 默认值7
SPI_Init(SPI1, &SPI_InitStructure);
//开启SPI外设
SPI_Cmd(SPI1, ENABLE);
//默认不选择从机
My_W_SS(1);
}
配置SPI时序基本单元
//起始条件
void My_SPI_Start(void)
{
//置低电平
My_W_SS(0);
}
//终止条件
void My_SPI_Stop(void)
{
//置高电平
My_W_SS(1);
}
//交换一个字节
uint8_t My_SPI_SwapByte(uint8_t ByteSend)
{
//等待TXE为1
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);
//写入数据
SPI_I2S_SendData(SPI1, ByteSend);
//等待RXNE为1 代表收到一个字节
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);
//读取DR
return SPI_I2S_ReceiveData(SPI1);
}
最终的程序现象与软件SPI读写现象一致
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。