您现在的位置是:首页 >学无止境 >STM32 硬件SPI读写W25Q64网站首页学无止境

STM32 硬件SPI读写W25Q64

2401- 2025-02-26 12:01:02
简介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读写现象一致

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。