chargeController/APP/hardwareDriver/Src/w25q256.c

318 lines
8.5 KiB
C
Raw Normal View History

2025-01-11 02:19:58 +00:00
#include <string.h>
#include "w25q256.h"
///@brief Flash相关引脚初始化
void Flash_GPIO_Init(void)
{
FLASH_CS_DISABLE;
FLASH_CLK_HIGH;
FLASH_MOSI_LOW;
}
///@brief 读取一个字节数据
static uint8_t Flash_ReadOneByte(void)
{
uint8_t retValue = 0;
FLASH_CLK_HIGH; //时钟线拉高,恢复时钟线为高电平
for(uint8_t i= 0; i < 8; i++)
{
retValue <<= 1;
FLASH_CLK_HIGH; //时钟线拉高,恢复时钟线为高电平
if(FLASH_MISO_READ)
{
retValue |= 0x01;
}
else
{
retValue &= 0xFE;
}
FLASH_CLK_LOW; //时钟线拉低,产生下降沿读出数据
}
FLASH_CLK_HIGH;
return (retValue);
}
///@brief 写入一个字节
static void Flash_WriteOneByte(uint8_t DataBuffer)
{
FLASH_CLK_LOW; //时钟线拉低,恢复时钟线为低电平
for(uint8_t i = 0; i < 8; i++)
{
FLASH_CLK_LOW; //时钟线拉低,恢复时钟线为低电平
if(DataBuffer & 0x80)
{
FLASH_MOSI_HIGH;
}
else
{
FLASH_MOSI_LOW;
}
DataBuffer <<= 1;
FLASH_CLK_HIGH; //时钟线拉高,产生上升沿写入数据
}
FLASH_CLK_LOW;
FLASH_MOSI_HIGH; //一字节数据传送完毕MOSI数据线置高表示空闲状态
}
///@brief 写指令
static void Flash_Write_CMD(uint8_t *pCMD)
{
#ifdef FLASH_W25Q256
for(uint8_t i = 0; i < 4; i++) //new add
{
Flash_WriteOneByte(pCMD[i]);
}
#endif
#ifdef FLASH_W25Q128
for(uint8_t i = 0; i < 3; i++) //new add
{
Flash_WriteOneByte(pCMD[i]);
}
#endif
}
///@brief 读取SR
static uint8_t Flash_ReadSR(void)
{
uint8_t retValue = 0;
FLASH_CS_ENABLE;
Flash_WriteOneByte(Flash_ReadSR_CMD);
retValue = Flash_ReadOneByte();
FLASH_CS_DISABLE;
return retValue;
}
///@brief 等待标志位
static void Flash_Wait_Busy(void)
{
uint32_t i =0;
while(((Flash_ReadSR() & FLASH_WRITE_BUSYBIT) == 0x01) && (i<0x1ffff))
{
i ++;
}
}
///@brief 写使能
static void Flash_Write_Enable(void)
{
FLASH_CS_ENABLE;
Flash_WriteOneByte(Flash_WriteEnable_CMD);
FLASH_CS_DISABLE;
}
#if 0
///@brief 进入4字节模式
void Enter4ByteAddrMode(void)
{
FLASH_CS_ENABLE; //使能器件
Flash_WriteOneByte(W25Q_4ByteAddrModeEnable); //进入4Byte地址模式W25Q128以上使用
FLASH_CS_DISABLE;
}
///@brief 退出4字节模式
void Exit4ByteAddrMode(void)
{
FLASH_CS_ENABLE; //使能器件
Flash_WriteOneByte(W25Q_Exit4ByteAddrModeEnable); //进入4Byte地址模式W25Q128以上使用
FLASH_CS_DISABLE;
}
#endif
///@brief 擦除区域
void Flash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number)
{
uint8_t pcmd[3] = {0};
Flash_Write_Enable();
FLASH_CS_ENABLE;
Flash_WriteOneByte(Flash_SecErase_CMD);
pcmd[0] = Block_Num;
pcmd[1] = Sector_Number<<4;
pcmd[2] = 0;
Flash_Write_CMD(pcmd);
FLASH_CS_DISABLE;
Flash_Wait_Busy();//每次擦除数据都要延时等待写入结束
return ;
}
///@brief 擦除块
void Flash_Erase_Block(uint8_t BlockNum)
{
uint8_t pcmd[3] = {0};
Flash_Write_Enable(); //写使能
FLASH_CS_ENABLE; //片选拉低
Flash_WriteOneByte(Flash_BlockErase_CMD); //传输Block擦除指令
pcmd[0] = BlockNum ; //传24位地址
Flash_Write_CMD(pcmd);
FLASH_CS_DISABLE;
Flash_Wait_Busy(); //每次擦除数据都要延时等待写入结束
return ;
}
///@brief 页写
void Flash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{
uint8_t pcmd[4] = {0};
Flash_Write_Enable();
FLASH_CS_ENABLE;
Flash_WriteOneByte(Flash_PageProgram_CMD);
#ifdef FLASH_W25Q256
pcmd[0] = (uint8_t)((WriteAddr&0xff000000)>>24); //new add
pcmd[1] = (uint8_t)((WriteAddr&0x00ff0000)>>16);
pcmd[2] = (uint8_t)((WriteAddr&0x0000ff00)>>8);
pcmd[3] = (uint8_t)WriteAddr;
#endif
#ifdef FLASH_W25Q128
pcmd[0] = (uint8_t)((WriteAddr&0x00ff0000)>>16);
pcmd[1] = (uint8_t)((WriteAddr&0x0000ff00)>>8);
pcmd[2] = (uint8_t)WriteAddr;
#endif
Flash_Write_CMD(pcmd);
for(uint32_t i = 0;i < WriteBytesNum; i++)
{
Flash_WriteOneByte(pBuffer[i]); //向Flash中写入最大一页256bytes字节数据
}
FLASH_CS_DISABLE;
Flash_Wait_Busy(); //每次写入一定数量的数据都要延时等待写入结束
return;
}
///@brief 连续写入多页
void Flash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{
uint16_t PageByteRemain = 0;
PageByteRemain = Flash_PAGEBYTE_LENGTH - WriteAddr%Flash_PAGEBYTE_LENGTH;
if(WriteBytesNum <= PageByteRemain)
{
PageByteRemain = WriteBytesNum;
}
while(1)
{
Flash_Write_Page(pBuffer,WriteAddr,PageByteRemain);
if(WriteBytesNum == PageByteRemain)
{
break;
}
else
{
pBuffer += PageByteRemain;
WriteAddr += PageByteRemain;
WriteBytesNum -= PageByteRemain;
if(WriteBytesNum > Flash_PAGEBYTE_LENGTH)
{
PageByteRemain = Flash_PAGEBYTE_LENGTH;
}
else
{
PageByteRemain = WriteBytesNum;
}
}
}
return;
}
///@brief 连续写入多页
uint8_t W25QXX_BUFFER[4096];
void W25Q128_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{
// volatile static int timeReadTemp1, timeReadTemp2, timeReadTemp3, timeReadTemp4, timeReadTemp5, timeReadTemp6;
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t *W25QXX_BUF;
W25QXX_BUF = W25QXX_BUFFER;
secpos = WriteAddr / 4096; //扇区地址
secoff = WriteAddr % 4096; //在扇区内的偏移
secremain = 4096 - secoff; //扇区剩余空间大小
if (WriteBytesNum <= secremain)
secremain = WriteBytesNum; //不大于4096个字节
while (1)
{
// timeReadTemp1 = HAL_GetTick();
Flash_Read(W25QXX_BUF, secpos * 4096, 4096); //读出整个扇区的内容
// timeReadTemp2 = HAL_GetTick();
for (i = 0; i < secremain; i++) //校验数据
{
if (W25QXX_BUF[secoff + i] != 0XFF)
break; //需要擦除
}
if (i < secremain) //需要擦除
{
Flash_Erase_Block(secpos); //擦除这个扇区
// timeReadTemp3 = HAL_GetTick();
for (i = 0; i < secremain; i++) //复制
{
W25QXX_BUF[i + secoff] = pBuffer[i];
}
Flash_Write_Page(W25QXX_BUF, secpos * 4096, 4096); //写入整个扇区
// timeReadTemp4 = HAL_GetTick();
// timeReadTemp5 = NumByteToWrite;
// timeReadTemp6 = WriteAddr;
}
else
Flash_Write_Page(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间.
if (WriteBytesNum == secremain)
break; //写入结束了
else //写入未结束
{
secpos++; //扇区地址增1
secoff = 0; //偏移位置为0
pBuffer += secremain; //指针偏移
WriteAddr += secremain; //写地址偏移
WriteBytesNum -= secremain; //字节数递减
if (WriteBytesNum > 4096)
secremain = 4096; //下一个扇区还是写不完
else
secremain = WriteBytesNum; //下一个扇区可以写完了
}
};
}
///@brief 读取数据
void Flash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum)
{
uint8_t pcmd[4] = {0};
FLASH_CS_ENABLE; //打开spiflash片选
Flash_WriteOneByte(Flash_ReadData_CMD);
#ifdef FLASH_W25Q256
pcmd[0] = (uint8_t)((ReadAddr&0xff000000)>>24); //new add
pcmd[1] = (uint8_t)((ReadAddr&0x00ff0000)>>16);
pcmd[2] = (uint8_t)((ReadAddr&0x0000ff00)>>8);
pcmd[3] = (uint8_t)ReadAddr;
#endif
#ifdef FLASH_W25Q128
pcmd[0] = (uint8_t)((ReadAddr&0x00ff0000)>>16);
pcmd[1] = (uint8_t)((ReadAddr&0x0000ff00)>>8);
pcmd[2] = (uint8_t)ReadAddr;
#endif
Flash_Write_CMD(pcmd);
for(uint32_t i = 0;i < ReadBytesNum; i++)
{
pBuffer[i] = Flash_ReadOneByte(); //读取SPIflash中指定bytes字节数据
}
FLASH_CS_DISABLE;
return ;
}