#include "main.h" /*-------------------------------------------------*/ /*函数名:初始化W25Qxx */ /*参 数:无 */ /*返回值:0:正确 */ /*-------------------------------------------------*/ void w25qxxInit(void) { GPIO_InitTypeDef GPIO_Initure; GPIOA_RCC_ENABLE; //使能端口A时钟 GPIO_Initure.Pin=Flash_CS_Pin; //设置PD0 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推免输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速模式 HAL_GPIO_Init(Flash_CS_Port,&GPIO_Initure); //设置 CS_DISENABLE; //CS无效信号 SPI1_Init(); //初始化SPI2接口 if(w25qxxReadID()==W25QxxID) { //读取ID,正确进入if w25qxxWriteEnable(); //写使能 } else { log_info("读取W25Q64失败!"); while(1);//卡死等待 } } /*-------------------------------------------------*/ /*函数名:W25Qxx擦写使能 */ /*参 数:无 */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxWriteEnable(void) { w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_WriteByte(W25Qxx_WriteEnable); //发送写使能 CS_DISENABLE; //CS无效信号 } /*-------------------------------------------------*/ /*函数名:W25Qxx擦写禁止 */ /*参 数:无 */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxWriteDisable(void) { w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_WriteByte(W25Qxx_WriteDisable); //发送写禁止 CS_DISENABLE; //CS无效信号 } /*-------------------------------------------------*/ /*函数名:读取W25Qxx芯片ID */ /*参 数:无 */ /*返回值:0XEF17 是W25Qxx的ID */ /*-------------------------------------------------*/ uint16_t w25qxxReadID(void) { uint8_t wdata[6] = {0x90,0x00,0x00,0x00,0x00,0x00}; //读取ID指令数据 uint8_t rdata[6]; //接收数据缓冲区 w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_WriteRead(wdata,rdata,6); //发送并接收数据 CS_DISENABLE; //CS无效信号 return (rdata[4]*256 + rdata[5]); //返回ID } /*-------------------------------------------------*/ /*函数名:W25Qxx等待空闲 */ /*参 数:无 */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxWaitBusy(void) { uint8_t res; do { CS_ENABLE; //CS有效信号 SPI1_WriteByte(W25Qxx_ReadStatusReg1); //发送读取状态寄存器1命令 res = SPI1_ReadByte(); //读取状态寄存器1 CS_DISENABLE; //CS无效信号 } while((res&0x01)==0x01); //等待BUSY位清空,表示空闲 } /*-------------------------------------------------*/ /*函数名:W25Qxx擦除一个扇区(4KB) */ /*参 数:NBsector:第几个扇区 (0~4095) */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxEraseSector(uint16_t NBsector) { uint8_t wdata[4]; //指令数据缓冲区 wdata[0] = W25Qxx_SectorErase; //扇区擦除指令 wdata[1] = (NBsector*4096)>>16; //A23~A16地址位 wdata[2] = (NBsector*4096)>>8; //A15~A8地址位 wdata[3] = (NBsector*4096)>>0; //A7~A0地址位 w25qxxWriteEnable(); //写使能 w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_Write(wdata,4); //发送数据 CS_DISENABLE; //CS无效信号 w25qxxWaitBusy(); //等待擦除完成 } /*-------------------------------------------------*/ /*函数名:W25Qxx擦除一个块(64KB) */ /*参 数:NBsector:第几个块 (0~255) */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxEraseBlock(uint8_t NBBlock) { uint8_t wdata[4]; //指令数据缓冲区 wdata[0] = W25Qxx_BlockErase; //块擦除指令 wdata[1] = (NBBlock*16*4096)>>16; //A23~A16地址位 wdata[2] = (NBBlock*16*4096)>>8; //A15~A8地址位 wdata[3] = (NBBlock*16*4096)>>0; //A7~A0地址位 w25qxxWriteEnable(); //写使能 w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_Write(wdata,4); //发送数据 CS_DISENABLE; //CS无效信号 w25qxxWaitBusy(); //等待擦除完成 } /*-------------------------------------------------*/ /*函数名:W25Qxx写入一页数据(256字节) */ /*参 数:wdata:待写入数据 */ /*参 数:NBPage:第几个页(0~65535) */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxWritePage(uint8_t* wbuff, uint16_t NBPage) { uint8_t wdata[4]; //指令数据缓冲区 wdata[0] = W25Qxx_PageProgram; //页(256B)写入指令 wdata[1] = (NBPage*256)>>16; //A23~A16地址位 wdata[2] = (NBPage*256)>>8; //A15~A8地址位 wdata[3] = (NBPage*256)>>0; //A7~A0地址位 w25qxxWriteEnable(); //写使能 w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_Write(wdata,4); //发送数据 SPI1_Write(wbuff,256); //发送数据 CS_DISENABLE; //CS无效信号 } /*-------------------------------------------------*/ /*函数名:W25Qxx读取数据 */ /*参 数:rdata:存放数据缓冲区 */ /*参 数:rAddr:读取的开始地址 */ /*参 数:len:读取多少字节数据 */ /*返回值:无 */ /*-------------------------------------------------*/ void w25qxxRead(uint8_t* rdata,uint32_t rAddr,uint32_t len) { uint8_t wdata[4]; //指令数据缓冲区 wdata[0] = W25Qxx_ReadData; //读数据指令 wdata[1] = rAddr>>16; //A23~A16地址位 wdata[2] = rAddr>>8; //A15~A8地址位 wdata[3] = rAddr>>0; //A7~A0地址位 w25qxxWaitBusy(); //等待空闲 CS_ENABLE; //CS有效信号 SPI1_Write(wdata,4); //发送数据 SPI1_Read(rdata,len); //接收数据 CS_DISENABLE; //CS无效信号 }