chargeController/APP/hardwareDriver/Src/w25q256.c

318 lines
8.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 ;
}