一、FLASH W25QXX
(一)、软件SPI读写W25QXX
(二)、硬件读写W25QXX
STM32CubeMX配置SPI通信(HAL库)
以stm32F407战舰版举例,由于战舰版和W25QXX芯片引脚已经连接完成,分别是PB3-PB5,使用cubemx配置SPI1时,但是软件会默认选择PA4-PA6复用SPI1,但是我们需要使用PB3-PB5怎么处理
硬件片选和软件片选的区别
所谓硬件片选指的是SPI本身具有片选信号,当我们通过SPI发送数据时,SPI外设自动拉低CS信号使能从机,发送完成后自动拉高CS信号释放从机,这个过程是不需要软件操作的。而软件片选则是需要使用GPIO作为片选信号,SPI在发送数据之前,需要先通过软件设置作为片选信号的GPIO输出低电平,发送完成之后再设置该GPIO输出高电平。一般选择软件片选。
写W25Q128驱动代码
W25Q128何GD25Q128相同
gd25q128.c
#include "gd25q128.h"
uint16_t GD25Q128_TYPE = 0;
uint32_t GD25Q128_SIZE = 0;
uint8_t GD25Q128_UID[8];
static void delay_us(uint32_t us)
{
uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
while (delay--)
{
;
}
}
//SPI读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
static uint8_t GD25Q128_SPI_ReadWriteByte(uint8_t TxData)
{
uint8_t RxData = 0X00;
if(HAL_SPI_TransmitReceive(&hspi1, &TxData, &RxData, 1, 1000) != HAL_OK)
{
RxData = 0XFF;
}
return RxData;
}
//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q128
//容量为16M字节,共有128个Block,4096个Sector
//初始化SPI FLASH的IO口
int GD25Q128_Init(void)
{
MX_SPI1_Init();
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);//将HOLD置高,操作eeprom
GD25Q128_CS_L(); /* 拉低选中 */
GD25Q128_SPI_ReadWriteByte(0XFF);
GD25Q128_CS_H(); /* 拉高取消 */
GD25Q128_TYPE = GD25Q128_ReadID(); // 读取FLASH ID.
GD25Q128_SIZE = GD25Q128_ReadCapacity(); // 读取容量
GD25Q128_ReadUniqueID(GD25Q128_UID); // 读取唯一ID
if((GD25Q128_TYPE & 0XC800) != 0XC800)
{
return -1;
}
return 0;
}
//读取GD25Q128的状态寄存器
//BIT7 6 5 4 3 2 1 0
//SPR RV TB BP2 BP1 BP0 WEL BUSY
//SPR:默认0,状态寄存器保护位,配合WP使用
//TB,BP2,BP1,BP0:FLASH区域写保护设置
//WEL:写使能锁定
//BUSY:忙标记位(1,忙;0,空闲)
//默认:0x00
uint8_t GD25Q128_ReadSR(void)
{
uint8_t byte = 0;
GD25Q128_CS_L(); //使能器件
GD25Q128_SPI_ReadWriteByte(GD25X_ReadStatusReg); //发送读取状态寄存器命令
byte = GD25Q128_SPI_ReadWriteByte(0Xff); //读取一个字节
GD25Q128_CS_H(); //取消片选
return byte;
}
//写GD25Q128状态寄存器
//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!!
void GD25Q128_Write_SR(uint8_t sr)
{
GD25Q128_CS_L(); //使能器件
GD25Q128_SPI_ReadWriteByte(GD25X_WriteStatusReg); //发送写取状态寄存器命令
GD25Q128_SPI_ReadWriteByte(sr); //写入一个字节
GD25Q128_CS_H(); //取消片选
}
//GD25Q128写使能
//将WEL置位
void GD25Q128_Write_Enable(void)
{
GD25Q128_CS_L(); //使能器件
GD25Q128_SPI_ReadWriteByte(GD25X_WriteEnable); //发送写使能
GD25Q128_CS_H(); //取消片选
}
//GD25Q128写禁止
//将WEL清零
void GD25Q128_Write_Disable(void)
{
GD25Q128_CS_L(); //使能器件
GD25Q128_SPI_ReadWriteByte(GD25X_WriteDisable); //发送写禁止指令
GD25Q128_CS_H(); //取消片选
}
//读取芯片ID
//返回值如下:
//0XC817,表示芯片型号为GD25Q128
uint16_t GD25Q128_ReadID(void)
{
uint16_t Temp = 0;
GD25Q128_CS_L();
GD25Q128_SPI_ReadWriteByte(0x90); //发送读取ID命令
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x00);
Temp |= GD25Q128_SPI_ReadWriteByte(0xFF) << 8;
Temp |= GD25Q128_SPI_ReadWriteByte(0xFF);
GD25Q128_CS_H();
return Temp;
}
uint32_t GD25Q128_ReadCapacity(void)
{
int i = 0;
uint8_t arr[4] = {0,0,0,0};
GD25Q128_CS_L();
GD25Q128_SPI_ReadWriteByte(0x5A);
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x84);
GD25Q128_SPI_ReadWriteByte(0x00);
for(i = 0; i < sizeof(arr); i++)
{
arr[i] = GD25Q128_SPI_ReadWriteByte(0xFF);
}
GD25Q128_CS_H();
return ((((*(uint32_t *)arr)) + 1) >> 3);
}
void GD25Q128_ReadUniqueID(uint8_t UID[8])
{
int i = 0;
GD25Q128_CS_L();
GD25Q128_SPI_ReadWriteByte(0x4B);
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x00);
GD25Q128_SPI_ReadWriteByte(0x00);
for(i = 0; i < 8; i++)
{
UID[i] = GD25Q128_SPI_ReadWriteByte(0xFF);
}
GD25Q128_CS_H();
}
//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void GD25Q128_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
uint16_t i;
GD25Q128_CS_L(); //使能器件
GD25Q128_SPI_ReadWriteByte(GD25X_ReadData); //发送读取命令
GD25Q128_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 16)); //发送24bit地址
GD25Q128_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 8));
GD25Q128_SPI_ReadWriteByte((uint8_t)ReadAddr);
for (i = 0; i < NumByte