W25Q64是华邦公司推出的大容量 基于SPI通信 的FLASH 产品,工作电压为 2.7~3.6V,存储容量为 64Mb(8MB),擦写周期可达 10万次,数据保存时间可达 20年。 W25Q64系列 Flash存储器与 普通串行Flash存储器 相比,其使用 更灵活、性能更出色,非常 适合用于存储声音、文本和数据。
W25Q64 有 32768个 可编程页,每页 256字节。
使用 页编程指令 就可以 每次编程 256字节。
使用 扇区擦除指令 可以 每次擦除 256字节。
使用 块擦除指令 可以 每次擦除 256 页。
使用 整片擦除指令 可以 擦除整个 芯片
————————————————
这是常用指令cube_mx的spi设置
设置PB0为cs选择引脚
W25Q64.C
#include "spi.h"
#include "main.h"
#include "gpio.h"
#include "W25Q64_INS.h"
/**
*@brief:CS置0(选择从机)
*@param:
*@retval:
*/
void W25Q64_W_CS()
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
}
/**
*@brief:CS置1(关闭从机)
*@param:
*@retval:
*/
void W25Q64_S_CS()
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
}
/**
*@brief:发送一个字节
*@param:
*@retval:
*/
HAL_StatusTypeDef SPI_TransmitOneByte(uint8_t byteData)
{
return HAL_SPI_Transmit(&hspi1, &byteData, 1, 0XFF);
}
/**
*@brief:接收一个字节
*@param:
*@retval:
*/
uint8_t SPI_ReceiveOneByte(void)
{
uint8_t byteData=0;
HAL_SPI_Receive(&hspi1, &byteData, 1, 0XFF);
return byteData;
}
/**
*@brief:发送多个字节
*@param:
*@retval:
*/
HAL_StatusTypeDef SPI_TransmitMultiByte(uint8_t *byteData,uint8_t size)
{
return HAL_SPI_Transmit(&hspi1, byteData, size,0XFF);
}
/**
*@brief:接收多个字节
*@param:
*@retval:
*/
uint8_t SPI_ReceiveMultiByte(uint8_t *byteData,uint8_t size)
{
HAL_SPI_Receive(&hspi1, byteData, size, 0XFF);
}
/**
*@brief:写使能
*@param:
*@retval:
*/
void W24Q64_W_Enable()
{
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_WRITE_ENABLE);
W25Q64_S_CS();
}
/**
*@brief:等待忙
*@param:
*@retval:
*/
void W25Q64_WaitBusy()
{
uint32_t timeout;
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_READ_STATUS_REGISTER_1);
timeout=100000;
SPI_TransmitOneByte(W25Q64_DUMMY_BYTE);
while((SPI_ReceiveOneByte()&0x01)==0x01)
{
SPI_TransmitOneByte(W25Q64_DUMMY_BYTE);
timeout--;
if(timeout==0)break;
}
W25Q64_S_CS();
}
/**
*@brief:读设备ID
*@param:
*@retval:
*/
uint16_t W25Q64_R_ID(void)
{
uint16_t Temp = 0;
W25Q64_W_CS(); //CS=0
SPI_TransmitOneByte(0x90); //???,0x90=Manufacturer/Device ID
SPI_TransmitOneByte(0x00); //dummy
SPI_TransmitOneByte(0x00); //dummy
SPI_TransmitOneByte(0x00); //0x00
Temp =SPI_ReceiveOneByte()<<8; //Manufacturer ID
Temp|=SPI_ReceiveOneByte(); //Device ID, ???????
W25Q64_S_CS(); //CS=1
return Temp;
}
/**
*@brief:扇区擦除
*@param:µØÖ·
*@retval:
*/
void W25Q64_EraseSector(uint32_t address)
{
W24Q64_W_Enable();
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_SECTOR_ERASE_4KB);
SPI_TransmitOneByte(address>>16);
SPI_TransmitOneByte(address>>8);
SPI_TransmitOneByte(address);
W25Q64_S_CS();
W25Q64_WaitBusy();
}
/**
*@brief:页编程
*@param:
*@retval:
*/
void W25Q64_W_Data(uint8_t *w25q64_W_data,uint8_t size,uint32_t address)
{
W24Q64_W_Enable();
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_PAGE_PROGRAM);
SPI_TransmitOneByte(address>>16);
SPI_TransmitOneByte(address>>8);
SPI_TransmitOneByte(address);
SPI_TransmitMultiByte(w25q64_W_data,size);
W25Q64_S_CS();
W25Q64_WaitBusy();
}
//扇区编程
void W25Q64_SectorW_Data(uint8_t *w25q64_W_data,uint16_t size,uint32_t address)
{
uint8_t i;
for(i=0;i<=size/256;i++)
{
W25Q64_W_Data(w25q64_W_data,255,address);
address+=0x000100;
w25q64_W_data+=256;
}
}
/**
*@brief:写入32位数据
*@param:
*@retval:
*/
void W25Q64_W_32bitData(uint32_t *w25q64_W_data,uint8_t size,uint32_t address)
{
uint8_t data[4];
W24Q64_W_Enable();
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_PAGE_PROGRAM);
SPI_TransmitOneByte(address>>16);
SPI_TransmitOneByte(address>>8);
SPI_TransmitOneByte(address);
for(uint8_t i=0;i<size;i++)
{
data[0]=*w25q64_W_data>>24;
data[1]=*w25q64_W_data>>16;
data[2]=*w25q64_W_data>>8;
data[3]=*w25q64_W_data;
SPI_TransmitMultiByte(data,4);
w25q64_W_data++;
}
W25Q64_S_CS();
W25Q64_WaitBusy();
}
/**
*@brief:读8位数据
*@param:·
*@retval:
*/
void W25Q64_R_Data(uint8_t *w25q64_R_data,uint8_t size,uint32_t address)
{
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_READ_DATA);
SPI_TransmitOneByte(address>>16);
SPI_TransmitOneByte(address>>8);
SPI_TransmitOneByte(address);
SPI_ReceiveMultiByte(w25q64_R_data,size);
W25Q64_S_CS();
}
//读扇区内数据
void W25Q64_SectorR_Data(uint8_t *w25q64_data,uint16_t size,uint32_t address)
{
uint8_t i;
for(i=0;i<=size/256;i++)
{
W25Q64_R_Data(w25q64_data,255,address);
address+=0x000100;
w25q64_data+=256;
}
}
/**
*@brief:读32位数据
*@param:
*@retval:
*/
void W25Q64_R_32bitData(uint32_t *w25q64_R_data,uint8_t size,uint32_t address)
{
uint8_t data[4];
W25Q64_W_CS();
SPI_TransmitOneByte(W25Q64_READ_DATA);
SPI_TransmitOneByte(address>>16);
SPI_TransmitOneByte(address>>8);
SPI_TransmitOneByte(address);
for(uint8_t i=0;i<size;i++)
{
SPI_ReceiveMultiByte(data,4);
*w25q64_R_data=data[0];
*w25q64_R_data=*w25q64_R_data<<8;
*w25q64_R_data|=data[1];
*w25q64_R_data=*w25q64_R_data<<8;
*w25q64_R_data|=data[2];
*w25q64_R_data=*w25q64_R_data<<8;
*w25q64_R_data|=data[3];
w25q64_R_data++;
}
W25Q64_S_CS();
}
W25Q64.H
#ifndef __W25Q64_H__
#define __W25Q64_H__
void W24Q64_W_Enable();
uint16_t W25Q64_R_ID();
void W25Q64_W_Data(uint8_t *w25q64_W_data,uint8_t size,uint32_t address);
void W25Q64_SectorW_Data(uint8_t *w25q64_W_data,uint16_t size,uint32_t address);
void W25Q64_W_32bitData(uint32_t *w25q64_W_data,uint8_t size,uint32_t address);
void W25Q64_R_Data(uint8_t *w25q64_R_data,uint8_t size,uint32_t address);
void W25Q64_SectorR_Data(uint8_t *w25q64_data,uint16_t size,uint32_t address);
void W25Q64_R_32bitData(uint32_t *w25q64_R_data,uint8_t size,uint32_t address);
void W25Q64_EraseSector(uint32_t address);
#endif
OLED使用硬件iic部分后继更新