W25Q256FV

/*******************************************************************************
* W25W256FV  256 M-Bit 32K Byte 

* 256 Byte One Page

*******************************************************************************/


#define CMD_RESET (INT8U)(0x99)
#define CMD_RESETEN (INT8U)(0x66)
#define  SET_4BYTEMODE_CMD             (INT8U)(0x11)     //设置4Byte_Mode
#define  WREN_CMD                      (INT8U)(0x06)     //写使能命令 使WEL 位置1;
#define  ERASE_ALL_CMD                 (INT8U)(0x60)     //擦除整片
#define  ERASE_SECTOR_CMD              (INT8U)(0x20)     //擦除一个扇区
#define  PAGE_WR_CMD                   (INT8U)(0x02)     //页写


#define  STAREG1_RD_CMD                (INT8U)(0x05)     //读状态寄存器1
#define  STAREG2_RD_CMD                (INT8U)(0x35)     //读状态寄存器2
#define  STAREG3_RD_CMD                (INT8U)(0x15)     //读状态寄存器3
#define  STAREG3_WT_CMD                (INT8U)(0x11)     //对状态寄存器3


#define  IBU_CMD                       (INT8U)(0x39)     //解除对整个W25Q256的写保护
#define  READ_ID_CMD                   (INT8U)(0x90)     //读manu id and device id


#define  FLASH_RD_CMD                  (INT8U)(0x13)     //整块Flash读
#define  ADDRESS_MAX                            0x1FFFFFF
#define  READ_ID                        0x18


#define  OFFSET_64K                             1024 * 64 //64K偏移量,用于解锁
#define  START_ADDR                             0x00000000
#define  SECTOR_SIZE                            4096     //扇区大小
#define  PAGE_SIZE                              256      //页大小


void MEM_Init(void);
void MEM_FlashChipErase(void);
void MEM_FlashLock(void);
void MEM_FlashUnLock(void);
void MEM_FlashRead(INT32U Addr,INT8U* pBuff,INT16U tNum);
void MEM_FlashWrite(INT32U Addr,INT8U* pBuff, INT16U tNum);
static void Flash_4ByteModeSet(void);
static void MEM_UnProtect(void);


INT32U Flash_Read_ID(void);
static void Flash_WriteEn(void);


static INT8U Flash_Buff[SECTOR_SIZE]@0x20002000;
void MEM_Test(void)
{
    INT8U cConstBuf[16] = {0x22,0x24,0x26,0x78,0x90,
                                0x22,0x34,0x56,0x78,0x90,

0x22,0x34,0x56,0x78,0x90,0x12};

    INT8U cBuff[16];
    MEM_Init();
  MEM_FlashRead(0x0000,cBuff,16);
MEM_FlashWrite(0x0000,cConstBuf,16);
MEM_FlashRead(0x0000,cBuff,16);
    MEM_FlashRead(0x0000,cBuff,16);

}




void MEM_Init(void)
{
Flash_4ByteModeSet();
MEM_UnProtect();
}
void Flash_SndCmd(INT8U cCmd)
{
    MCU_MemSPI_CS(IOHILO_LO);
    MCU_MemSPI_Snd(&cCmd,1);
    MCU_MemSPI_CS(IOHILO_HI);
}
BOOL Flash_ReadMode4(INT8U* pStatus)
{
INT8U cBuff[2];
BOOL  bSta;


bSta = FALSE;
cBuff[0] = STAREG3_RD_CMD;
    MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 1); /*发读状态寄存器3 命令*/
MCU_MemSPI_Rcv(pStatus,1);
    MCU_MemSPI_CS(IOHILO_HI);
   
    if ((*pStatus) & (1 << 0) == 1) /*判断当前的模式是3Byte还是4Byte*/
    {
        bSta = TRUE;
    }


return bSta;
}
/***********************************************************************
  函数名称:Flash_WriteEn
  函数功能:SPI写使能
  入口参数:无
  出口参数:无
 ************************************************************************/


static void Flash_WriteEn(void)
{
INT8U Cmd;

    MCU_MemSPI_CS(IOHILO_LO);
Cmd = WREN_CMD;
    MCU_MemSPI_Snd(&Cmd,1);
    MCU_MemSPI_CS(IOHILO_HI);
    
    
}    


/**************************************************************************
  函数名称:FLASH_WaitForWriteEnd
  函数功能:读Flash芯片状态寄存器的值并且循环读取标志位直到写周期结束
  入口参数:无
  出口参数:无
 *************************************************************************/
static void FLASH_WaitForWriteEnd(void)
{
INT8U cBuff[4];
    
    cBuff[0] = STAREG1_RD_CMD;


    MCU_MemSPI_CS(IOHILO_LO);


    MCU_MemSPI_Snd(cBuff,1); //读取Flash 状态寄存器1
   
    do
    {
MCU_MemSPI_Rcv(cBuff,1); //读状态寄存器的数据;
    }while ((cBuff[0] & 0x01) == 0x01); //若没有写完则一直等待,保持CS=0
    
    MCU_MemSPI_CS(IOHILO_HI);


}
/*********************************************************************
  函数名称:Flash_4ByteModeSet
  函数功能:把Flash设置成4字节模式。                  
 *********************************************************************/     
static void Flash_4ByteModeSet(void)
{
INT8U cBuff[4];
INT8U status;


if(Flash_ReadMode4(&status)==TRUE)
{
return;
}

    while (1)
    {
        Flash_SndCmd(WREN_CMD);

cBuff[0] = SET_4BYTEMODE_CMD; /*设置4 字节编程模式*/
cBuff[1] = status | (1 << 1); /**** S17置1 ****/


MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff,2);
        MCU_MemSPI_CS(IOHILO_HI);



        FLASH_WaitForWriteEnd(); /*等待写完*/


Flash_SndCmd(CMD_RESETEN);
MCU_DlyXus(1);

Flash_SndCmd(CMD_RESET);
MCU_DlyXus(30);// Delay 30Us

if(Flash_ReadMode4(&status)==TRUE)
        {
            return ;   
        }
    }/*loop for the 4bye mode set*/
}


/*********************************************************************
  函数名称:Flash_ChipErase
  函数功能:整片擦除                  
 *********************************************************************/         
void MEM_FlashChipErase(void)
{
INT8U cCmdBuff[4];

Flash_WriteEn();


cCmdBuff[0] = ERASE_ALL_CMD;
MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cCmdBuff,1);
MCU_MemSPI_CS(IOHILO_HI);


//等待擦除完成
FLASH_WaitForWriteEnd();
}




/************************************************************************
  函数名称:Flash_Sector_Erase
  函数功能:Flash的扇区擦除
  入口参数:@Sector_Num: 将要擦除的扇区号
 *************************************************************************/
void MEM_FlashEraseSector(INT16U Sector_Num)
{
INT8U  cSendCmd[8];
    INT32U tWriteAddr;
 
    tWriteAddr = Sector_Num * SECTOR_SIZE;


    Flash_WriteEn();
     
cSendCmd[0] = ERASE_SECTOR_CMD;
cSendCmd[1] = (tWriteAddr & 0xff000000) >> 24;
cSendCmd[2] = (tWriteAddr & 0xff0000) >> 16;
cSendCmd[3] = (tWriteAddr & 0xff00) >> 8;
cSendCmd[4] = tWriteAddr & 0xff;


    MCU_MemSPI_CS(IOHILO_LO);
    MCU_MemSPI_Snd(cSendCmd,5);
    MCU_MemSPI_CS(IOHILO_HI);
     
    FLASH_WaitForWriteEnd(); //等待擦除完成
}


/************************************************************************
  函数名称:Flash_PageWrite
  函数功能:Flash  页写
  入口参数:
  tBuf---------->待发数据指针
  tWriteAddr---->发送至Flash的地址(字节对齐)(4字节地址最大2000000(即32M个字节))
  tNum---------->发送数据个数(最大256个)
 *************************************************************************/
static void Flash_PageWrite(INT8U* tBuf,INT32U tWriteAddr,INT16U tNum)
{
INT8U cSendCmd[8];

    if (tWriteAddr > ADDRESS_MAX)
        return ;


    Flash_WriteEn();


cSendCmd[0] = PAGE_WR_CMD;
cSendCmd[1] = (tWriteAddr & 0xff000000) >> 24;
cSendCmd[2] = (tWriteAddr & 0xff0000) >> 16;
cSendCmd[3] = (tWriteAddr & 0xff00) >> 8;
cSendCmd[4] = tWriteAddr & 0xff;

    MCU_MemSPI_CS(IOHILO_LO);

MCU_MemSPI_Snd(cSendCmd,5);
MCU_MemSPI_Snd(tBuf,tNum);


    MCU_MemSPI_CS(IOHILO_HI);

    FLASH_WaitForWriteEnd();

   
}


/************************************************************************
  函数名称:Flash_Write_NoCheck
  函数功能:在指定地址开始写入指定长度的数据,但是要确保地址不越界! 具有自动换页功能 
  注意:在写之前先擦除将要写入的地址


  入口参数:
  tBuf---------->待发数据指针
  tWriteAddr---->发送至Flash的地址(4字节地址最大2000000(即32M个字节))
  tNum---------->发送数据个数(65536)
  返回值:
 *************************************************************************/
static void Flash_Write_NoCheck(INT8U* pBuffer, INT32U WriteAddr, INT32U NumByteToWrite)   
{
    INT16U Page_Remain;


    Page_Remain = PAGE_SIZE - WriteAddr % PAGE_SIZE;   //计算当前页剩余字节数;
    if (NumByteToWrite <= Page_Remain)
    {
        Page_Remain = NumByteToWrite;  
    }

    while (1)
    {
        Flash_PageWrite(pBuffer, WriteAddr, Page_Remain);  

        if (NumByteToWrite == Page_Remain)
        {
            break;   /*表示当前数据已经写完*/
        }
        else
        {
            pBuffer += Page_Remain;                   
            WriteAddr += Page_Remain; 
            NumByteToWrite -= Page_Remain; 
            if (NumByteToWrite > PAGE_SIZE)
            {
                Page_Remain = PAGE_SIZE;             //将写入数据大于256个
            }
            else
            {
                Page_Remain = NumByteToWrite;       //将写数据不足256个
            }
        }
    }
}


/************************************************************************
  函数名称:Flash_Write
  函数功能:在指定地址开始写入指定长度的数据(该函数带擦除操作!);
  入口参数:
  pBuffer---------->数据缓冲区指针
  WriteAddr---->任意Flash地址,不用担心该地址处是否已经擦除
  NumByteToWrite---------->将写入到数据个数(最大65535即一个Block大小)
 *************************************************************************/






void MEM_FlashWrite(INT32U WriteAddr, INT8U *pBuffer, INT16U NumByteToWrite)   
{
    INT32U i;
    INT32U Sector_Addr;
    INT32U Sector_Num;   
    INT32U Sector_Offest;
    INT32U Sector_Remain;


    /*calculate the beginning address of the current sector*/
    Sector_Addr = (WriteAddr / SECTOR_SIZE) * SECTOR_SIZE;   
    /*calculate the Sector number according to the WriteAddr*/
    Sector_Num = WriteAddr / SECTOR_SIZE;
    /*calculate the offest number of the sector*/
    Sector_Offest = WriteAddr % SECTOR_SIZE;
    /*calculate the remain of the sector*/
    Sector_Remain = SECTOR_SIZE - Sector_Offest;


    if (NumByteToWrite <= Sector_Remain)  
        Sector_Remain = NumByteToWrite;
    while (1)
    {
        /*copy the data writen previously into the sector to Flash_Buff*/
        MEM_FlashRead(Sector_Addr, Flash_Buff, SECTOR_SIZE);
        for(i = 0; i < Sector_Remain; i++) 
        {
            if (Flash_Buff[Sector_Offest + i] != 0xFF) break;   //表明需要擦除 
        
        }
        if(i < Sector_Remain) 
        {
            /*erase the Sector_Num*/
            MEM_FlashEraseSector(Sector_Num);  
           
            for(i = 0; i < Sector_Remain; i++)
                Flash_Buff[Sector_Offest + i] = pBuffer[i];
            /*write the data including previous data and the portion of new input data into the whole sector*/
            Flash_Write_NoCheck(Flash_Buff, Sector_Addr, SECTOR_SIZE);
        }
        else 
        {
            Flash_Write_NoCheck(pBuffer, WriteAddr, Sector_Remain);
        }


        if (NumByteToWrite == Sector_Remain)
            break; 
        else
        {
            Sector_Addr += SECTOR_SIZE;
            Sector_Num++;       //下一个扇区号
            Sector_Offest = 0; 
            pBuffer += Sector_Remain;
            NumByteToWrite -=Sector_Remain; 
            Sector_Remain = SECTOR_SIZE;  //默认写入4096个字节
            if (NumByteToWrite < SECTOR_SIZE) Sector_Remain = NumByteToWrite;  //当此次写入的数据不足一个扇区大小时。
        }


    }


}


/************************************************************************
  函数名称:Flash_Read
  函数功能:在整个Flash 范围内读取任意指定的地址开始处的数据
  入口参数:
  pBuf---------->接收数据缓冲区指针
  tWriteAddr---->读取的Flash地址
  tNum---------->读取数据个数
 *************************************************************************/
void MEM_FlashRead(INT32U tReadAddr, INT8U* pBuf, INT16U tNum)
{
INT8U   cSend[8];

cSend[0] = FLASH_RD_CMD;
cSend[1] = (tReadAddr & 0xff000000) >> 24;
cSend[2] = (tReadAddr & 0xff0000) >> 16;
cSend[3] = (tReadAddr & 0xff00) >> 8;
cSend[4] = tReadAddr & 0xff;

    MCU_MemSPI_CS(IOHILO_LO);


MCU_MemSPI_Snd(cSend,5);


MCU_MemSPI_Rcv(pBuf, tNum);


    MCU_MemSPI_CS(IOHILO_HI);





}






/************************************************************************
  函数名称:Spi_UnlockMemery
  函数功能:对于W25Q64,上电后要进行解锁操作
  入口参数:无
 *************************************************************************/


/*The device does't use the protect scheme of the Individual Block Locks by default,
 *so there is no neccessary to use the function.
 */
void MEM_FlashUnLock(void)
{
INT8U   cBuff[4];
    INT32U  i;


    for (i = 0; i < 64; i++)
    {
cBuff[0] = IBU_CMD;
cBuff[1] = START_ADDR + i * OFFSET_64K;

        MCU_MemSPI_CS(IOHILO_LO); 
MCU_MemSPI_Snd(cBuff, 2);
        MCU_MemSPI_CS(IOHILO_HI);
    }


}


int MEM_Check(void)
{
INT8U  cBuff[8];
    INT32U cError;


cError = 0;
cBuff[0] = READ_ID_CMD;
cBuff[1] = 0;
cBuff[2] = 0;
cBuff[3] = 0;


    MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 5);
    MCU_MemSPI_Rcv(cBuff,2);
    MCU_MemSPI_CS(IOHILO_HI);


if(READ_ID!=cBuff[0])
{
cError = 1;
}
else
{
if(0xEF!=cBuff[1])
{
cError = 2;
}
}
    return cError;
}
INT32U Flash_Read_ID(void)
{
INT8U  cBuff[8];
    INT32U Id;


cBuff[0] = READ_ID_CMD;
cBuff[1] = 0;
cBuff[2] = 0;
cBuff[3] = 0;
cBuff[4] = 0;

    MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 5);
    MCU_MemSPI_Rcv(cBuff,2);
    MCU_MemSPI_CS(IOHILO_HI);
   
    Id  = cBuff[0] << 8;
    Id |= cBuff[1];
    
    return Id;
}


/*关闭写独立扇区/块保护*/
static void MEM_UnProtect(void)
{
INT8U cBuff[4];
INT8U  status;
    
    
do {
cBuff[0] = STAREG3_RD_CMD;
        MCU_MemSPI_CS(IOHILO_LO);
MCU_MemSPI_Snd(cBuff, 1);
MCU_MemSPI_Rcv(&status,1);
MCU_MemSPI_CS(IOHILO_HI);

        if ((status & (1 << 2)) == 0)
        {
            return ;
        }

        Flash_WriteEn();     


cBuff[0] = STAREG3_WT_CMD;
cBuff[1] = status & ~(1 << 2);

        MCU_MemSPI_CS(IOHILO_LO); 
MCU_MemSPI_Snd(cBuff,2);
        MCU_MemSPI_CS(IOHILO_HI);
        
    }while (1);
}














 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缥缈孤鸿_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值