【BLE】TLSR8258開發記錄之7--SPI驅動W25Q16U

1、說明

基於SDK3.x(非3.4)移植FATFS文件系統,泰凌微提供的U盤demo工程

2、操作

A.修改drivers/8258/spi.c和spi.h
其中在spi.c中添加以下代碼(SPI驅動相關函數定義)

//MG add
void MG_spi_earse(unsigned int addr,GPIO_PinTypeDef CSPin)
{
       gpio_write(CSPin,0);//CS level is low
       reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
       reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
       reg_spi_data = 0x20;
       while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
     reg_spi_data = (addr>>16)&0xFF;
       while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
       reg_spi_data = (addr>>8)&0xFF;
       while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
       reg_spi_data = (addr)&0xFF;
       while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
     gpio_write(CSPin,1);//CS level is high
}
void MG_spi_Write_Enable(GPIO_PinTypeDef CSPin)
{
    unsigned char cmd = 0x06;
    gpio_write(CSPin,0);//CS level is low
      reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
      reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
      reg_spi_data = cmd;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      gpio_write(CSPin,1);//CS level is high
}
void MG_spi_Standly(GPIO_PinTypeDef CSPin)
{
    unsigned char cmd = 0xAB;
    gpio_write(CSPin,0);//CS level is low
      reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
      reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
      reg_spi_data = cmd;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      gpio_write(CSPin,1);//CS level is high
}
void MG_spi_write(unsigned int addr, unsigned char*buf, unsigned char  len,GPIO_PinTypeDef CSPin)
{
    unsigned char cmd = 0x02;
    unsigned char i=0;
    //MG_spi_Write_Enable(GPIO_PD6);
    gpio_write(CSPin,0);//CS level is low
      reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
      reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
      reg_spi_data = cmd;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      reg_spi_data = (addr>>16)&0xFF;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      reg_spi_data = (addr>>8)&0xFF;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      reg_spi_data = (addr)&0xFF;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      for(i=0; i<len ;i++)
      {
            reg_spi_data = buf[i];
            while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      }
      gpio_write(CSPin,1);//CS level is high
}
void MG_spi_read(unsigned int addr, unsigned char*buf, unsigned char  len,GPIO_PinTypeDef CSPin)
{
      unsigned char cmd = 0x03;
      unsigned char i=0;
      unsigned char temp;
      //MG_spi_Write_Enable(GPIO_PD6);
    gpio_write(CSPin,0);//CS level is low
      reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
      reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
      reg_spi_data = cmd;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      reg_spi_data = (addr>>16)&0xFF;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      reg_spi_data = (addr>>8)&0xFF;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      reg_spi_data = (addr)&0xFF;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
       reg_spi_ctrl |=FLD_SPI_DATA_OUT_DIS;
//        /***when the read_bit was set 1,you can read 0x800008 to take  eight clock cycle***/
          reg_spi_ctrl |= FLD_SPI_RD; //enable read,0x09-bit3 : 0 for  read ,1 for write
          temp = reg_spi_data; //first byte isn't useful data,only take  8 clock cycle
          while(reg_spi_ctrl &FLD_SPI_BUSY ); //wait reading finished
      for(i=0; i<len ;i++)
      {
            buf[i] = reg_spi_data;
            while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      }
      gpio_write(CSPin,1);//CS level is high
}
void MG_spi_readID(unsigned char *buf,GPIO_PinTypeDef CSPin)
{
      unsigned char cmd[4] = {0x90,0x00,0x00,0x00};
      unsigned char i = 0;
    unsigned char temp;
      gpio_write(CSPin,0);//CS level is low
      reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
      reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
      for(i=0; i<4; i++)
      {
            reg_spi_data = cmd[i];
            while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
      }
      reg_spi_ctrl |=FLD_SPI_DATA_OUT_DIS;
    /***when the read_bit was set 1,you can read 0x800008 to take eight  clock cycle***/
    reg_spi_ctrl |= FLD_SPI_RD; //enable read,0x09-bit3 : 0 for read ,1  for write
    temp = reg_spi_data; //first byte isn't useful data,only take 8 clock  cycle
    while(reg_spi_ctrl &FLD_SPI_BUSY ); //wait reading finished
    for(i=0; i<2 ;i++)
    {
       buf[i] = reg_spi_data;
       while(reg_spi_ctrl &FLD_SPI_BUSY ); //wait reading finished
    }
    gpio_write(CSPin,1);//CS level is high
}
void MG_spi_write_byte(unsigned char byte)
{
      reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi  data output
      reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for  read ,1 for write
      reg_spi_data = byte;
      while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
}
void MG_spi_write_nbyte(unsigned char *buf, unsigned short int len)
{
    unsigned short int i = 0 ;
    for(i=0; i<len; i++)
    {
        MG_spi_write_byte(*buf++);
    }
}
unsigned char MG_spi_read_byte()
{
    unsigned char dat = 0;
    reg_spi_ctrl |=FLD_SPI_DATA_OUT_DIS;
    reg_spi_ctrl |= FLD_SPI_RD;
    dat = reg_spi_data; //take 8 clock cycles
    while(reg_spi_ctrl & FLD_SPI_BUSY ); //wait reading finished
    return dat;
}
void MG_spi_read_nbyte(unsigned char *buf, unsigned int len)
{
      unsigned int i = 0;
      unsigned char temp;
    temp = MG_spi_read_byte();
      for(i=0; i<len; i++)
      {
          *buf++ = MG_spi_read_byte();
      }
}

在spi.h中添加以下代碼(SPI驅動相關函數聲明)

//MG add
extern void MG_spi_earse(unsigned int addr,GPIO_PinTypeDef CSPin);
extern void MG_spi_Write_Enable(GPIO_PinTypeDef CSPin);
extern void MG_spi_Standly(GPIO_PinTypeDef CSPin);
extern void MG_spi_write(unsigned int addr, unsigned char*buf, unsigned  char len,GPIO_PinTypeDef CSPin);
extern void MG_spi_read(unsigned int addr, unsigned char*buf, unsigned  char len,GPIO_PinTypeDef CSPin);
extern void MG_spi_readID(unsigned char *buf,GPIO_PinTypeDef CSPin);
void MG_spi_write_nbyte(unsigned char *buf, unsigned short int len);
extern void MG_spi_read_nbyte(unsigned char *buf, unsigned int len);
#define  MG_SPI_CS_LOW(CSPin)  gpio_write(CSPin,0)
#define  MG_SPI_CS_HIGH(CSPin)  gpio_write(CSPin,1)

B.在8258_USB_Disk_Demo中新建MG_SPI_Flash.c和MG_SPI_Flash.h
其中在MG_SPI_Flash.c中添加以下代碼(W25Q16U驅動相關函數定義)

#include "MG_SPI_Flash.h"
/*************************
Flash parameter define
*************************/
//Device id
#define W25Q16_MAN_ID                     0x85
#define W25Q16_DEV_ID                     0x14
/* Flash instruction list define */
#define W25Q16_WRTIEENABLE                0x06
#define W25Q16_WRTIEDISENABLE             0x04
#define W25Q16_READSTATUSREG              0x05
#define W25Q16_WRITESTATUSREG             0x01
#define W25Q16_READDATA                       0x03
#define W25Q16_FASTREADDATA                   0x0B
#define W25Q16_FASTREADDUAL                   0x3B
#define W25Q16_PAGEPROGRAM                    0x02
#define W25Q16_BLOCKERASE                     0xD8
#define W25Q16_SECTORERASE                    0x20
#define W25Q16_CHIPERASE                      0xC7
#define W25Q16_POWERDOWN                    0xB9
#define W25Q16_RELEASEPOWERDOWN               0xAB
#define W25Q16_DEVICEID                       0xAB
#define W25Q16_MANUFACTDEVICEID               0x90
#define W25Q16_JEDECDEVICEID              0x9F
#define W25Q16_BUSY_BIT                   0x01//確認Flash是否處於忙狀態Bit位
#define W25Q16_SECTORSIZE                 4096
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_ReadID()
*【輸入參數】: 無
*【輸出參數】: false:ID驗證失敗
               true:ID驗證成功
*【功    能】: 驗證W25Q16 device ID
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_ReadID()
{
  unsigned char ReadIdCmd[4] = {0x90,0x00,0x00,0x00};
  unsigned char rxbuf[2];
  MG_SPI_CS_LOW(MG_CS_PIN);
  MG_spi_write_nbyte(ReadIdCmd,4);
  MG_spi_read_nbyte(rxbuf,2);
  MG_SPI_CS_HIGH(MG_CS_PIN);
  if(rxbuf[0] == W25Q16_MAN_ID ||
     rxbuf[1] == W25Q16_DEV_ID )
  {
        //printf("data is : %d  %d\r\n",rxbuf[0],rxbuf[1]);
      return true;
  }
  return false;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_ReadSR()
*【輸入參數】: 無
*【輸出參數】: status:W25Q16當前狀態寄存器的值
*【功    能】: 讀取W25Q16狀態寄存器
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
static unsigned char Megain_SPIFlash_ReadSR()
{
      unsigned char status[1] = {0};
      unsigned char ReadSR_Cmd[1] = {W25Q16_READSTATUSREG};
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(ReadSR_Cmd,1);
    MG_spi_read_nbyte(status,1);
    MG_SPI_CS_HIGH(MG_CS_PIN);
    return status[0];
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_WaitBusy()
*【輸入參數】: 無
*【輸出參數】: 無
*【功    能】: 等待W25Q16忙
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
static void Megain_SPIFlash_WaitBusy()
{
    while((Megain_SPIFlash_ReadSR()&0x01));
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_WaitReady()
*【輸入參數】: 無
*【輸出參數】: 0:Flash芯片已經Ready
*【功    能】: 等待W25Q16空閒
*【作    者】: 黃金旭
*【修改時間】:2018.12.08
*******************************************************************************/
static int Megain_SPIFlash_WaitReady()
{
    unsigned char status;
    while(1)
    {
        status = Megain_SPIFlash_ReadSR();
        if(!(status & W25Q16_BUSY_BIT))         //Ready
        {
            break;
        }
    }
    return 0;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_WriteEnable()
*【輸入參數】: 無
*【輸出參數】: true:已經開啓寫使能
               false:未成功開啓寫使能
*【功    能】: W25Q16寫使能
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
static bool Megain_SPIFlash_WriteEnable()
{
    unsigned char WtiteEnable_Cmd = W25Q16_WRTIEENABLE;
    unsigned char status = 0;
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(&WtiteEnable_Cmd,1);
    MG_SPI_CS_HIGH(MG_CS_PIN);
    status = Megain_SPIFlash_ReadSR();
    if(status&0x02)
    {
        return true;
    }
    return false;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_Write(uint32_t address, uint8_t len,  uint8_t *buf)
*【輸入參數】: 無
*【輸出參數】: true:開啓寫使能,且SR寄存器不爲忙
               false:未成功開啓寫使能
*【功    能】: W25Q16寫操作
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_Write(unsigned int address, unsigned char len,  unsigned char *buf)
{
      unsigned char wbuf[4];
    bool status = false;
    //Megain_SPIFlash_ReleasePowerDown();
    delay_us(100);
    while(len>0)
    {
        Megain_SPIFlash_WaitReady();
        status = Megain_SPIFlash_WriteEnable();
        if(status == false)
        {
            return false;
        }
        unsigned int ilen;
        ilen = 256 - (address % 256);
        if (len < ilen)
        {
            ilen = len;
        }
        wbuf[0] = W25Q16_PAGEPROGRAM;
        wbuf[1] = (address >> 16);
        wbuf[2] = (address >> 8);
        wbuf[3] = (address)&0xff;
        address += ilen;
        len -= ilen;
        MG_SPI_CS_LOW(MG_CS_PIN);
        MG_spi_write_nbyte(wbuf,sizeof(wbuf));
        MG_spi_write_nbyte(buf,ilen);
        MG_SPI_CS_HIGH(MG_CS_PIN);
        Megain_SPIFlash_WaitBusy();
        buf += ilen;
    }
    //Megain_SPIFlash_PowerDown();
        return true;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_Read(uint32_t address, uint8_t len, uint8_t  *buf)
*【輸入參數】: 無
*【輸出參數】: true:開啓寫使能,且SR寄存器不爲忙
               false:未成功開啓寫使能
*【功    能】: W25Q16頁編程
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_Read(unsigned int address, unsigned int len,  unsigned char *buf)
{
      unsigned char wbuf[4];
    wbuf[0] = W25Q16_READDATA;
    wbuf[1] = (address>>16);
    wbuf[2] = (address>>8);
    wbuf[3] = (address)&0xFF;
    //Megain_SPIFlash_ReleasePowerDown();
    //Megain_SPIFlash_WaitReady();
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(wbuf,sizeof(wbuf));
    MG_spi_read_nbyte(buf,len);
    MG_SPI_CS_HIGH(MG_CS_PIN);
   // if(!Megain_SPIFlash_WaitReady())
   // {
   //     return true;
   // }
   //Megain_SPIFlash_PowerDown();
   // return false;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_EraseChip()
*【輸入參數】: 無
*【輸出參數】: 無
*【功    能】: W25Q16片擦
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
void Megain_SPIFlash_EraseChip()
{
    unsigned char wbuf[1];
    wbuf[0] = W25Q16_CHIPERASE;
    Megain_SPIFlash_WriteEnable();
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(wbuf,sizeof(wbuf));
    MG_SPI_CS_HIGH(MG_CS_PIN);
    Megain_SPIFlash_WaitBusy();
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_EraseSector(uint32_t address)
*【輸入參數】: 無
*【輸出參數】: 無
*【功    能】: W25Q16扇區擦(4K)
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_EraseSector(unsigned int address, unsigned int len)
{
    unsigned char wbuf[4];
    bool status = false;
    wbuf[0] = W25Q16_SECTORERASE;
    wbuf[1] = (address>>16);
    wbuf[2] = (address>>8);
    wbuf[3] = (address)&0xFF;
    status = Megain_SPIFlash_WriteEnable();
    if(status == false)
    {
        return false;
    }
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(wbuf,sizeof(wbuf));
    MG_SPI_CS_HIGH(MG_CS_PIN);
    Megain_SPIFlash_WaitBusy();
    return true;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_PowerDown()
*【輸入參數】: 無
*【輸出參數】: 無
*【功    能】: W25Q16 Power down模式
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
void Megain_SPIFlash_PowerDown()
{
    unsigned char wbuf[1];
    wbuf[0] = W25Q16_POWERDOWN;
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(wbuf,sizeof(wbuf));
    MG_SPI_CS_HIGH(MG_CS_PIN);
    delay_us(10);
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_ReleasePowerDown()
*【輸入參數】: 無
*【輸出參數】: 無
*【功    能】: W25Q16 解除Power down模式
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
void Megain_SPIFlash_ReleasePowerDown()
{
      unsigned char wbuf[1];
    wbuf[0] = W25Q16_RELEASEPOWERDOWN;
    MG_SPI_CS_LOW(MG_CS_PIN);
    MG_spi_write_nbyte(wbuf,sizeof(wbuf));
    MG_SPI_CS_HIGH(MG_CS_PIN);
    delay_us(10);
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_Init()
*【輸入參數】: 無
*【輸出參數】: 無
*【功    能】: SPI 初始化
*【作    者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
unsigned char Megain_SPIFlash_Init()
{
      unsigned char rx_data[2] = {0,0};
      unsigned char tx_data[2] = {0x02,0x06};
      /*
       *          SDO  SDI  SCK  CN
       *          A2   A3   A4   D6
       *          B7   B6   D7   D2
       */
      spi_master_set_pin(0);//
      spi_master_set_cs_pin(GPIO_PD6);
      spi_master_init(3,0);//4M、mode 0
      //Megain_SPIFlash_EraseChip();
      //Megain_SPIFlash_ReadID();
      //Megain_SPIFlash_EraseSector(0x00002000,4096);
    //Megain_SPIFlash_Read(0x00002000,2,rx_data);
      //printf("data is : %d  %d\r\n",rx_data[0],rx_data[1]);
      //Megain_SPI_Flash_Write_NoCheck(0x00002000,2,tx_data);
      //Megain_SPIFlash_Write(0x00002000,2,tx_data);
      //Megain_SPIFlash_Read(0x00002000,2,rx_data);
      //Megain_SPIFlash_EraseSector(0x00002000,4096);
      //printf("data is : %d  %d\r\n",rx_data[0],rx_data[1]);
      //Megain_SPIFlash_Read(0x00002000,2,rx_data);
      //printf("data is : %d  %d\r\n",rx_data[0],rx_data[1]);
      //if(rx_data[0] == tx_data[0] && rx_data[1] == tx_data[1])
      //{
        return 0;
      //}
      //else
      //{
      //    return 1;
      //}
}
//SPI在一頁(0~65535)內寫入少於256個字節的數據
//在指定地址開始寫入最大256字節的數據
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大256),該數不應該超過該頁的剩餘字節數!!!
void Megain_SPI_Flash_Write_Page(unsigned int address ,unsigned short  int len, unsigned char *buf)
{
    unsigned char wbuf[4];
    //Megain_SPIFlash_ReleasePowerDown();
    Megain_SPIFlash_WriteEnable();
    MG_SPI_CS_LOW(MG_CS_PIN);
    wbuf[0] = W25Q16_PAGEPROGRAM;
    wbuf[1] = (address >> 16);
    wbuf[2] = (address >> 8);
    wbuf[3] = (address)&0xff;
    MG_spi_write_nbyte(wbuf,4);
    MG_spi_write_nbyte(buf,len);
    MG_SPI_CS_HIGH(MG_CS_PIN);
    Megain_SPIFlash_WaitBusy();
}
//無檢驗寫SPI FLASH
//必須確保所寫的地址範圍內的數據全部爲0XFF,否則在非0XFF處寫入的數據將失敗!
//具有自動換頁功能
//在指定地址開始寫入指定長度的數據,但是要確保地址不越界!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)
//CHECK OK
//void Megain_SPI_Flash_Write_NoCheck(unsigned int address, unsigned  short int len, unsigned char *buf)
//{
//    unsigned short int pageremain;
//    pageremain=256-address%256; //單頁剩餘的字節數
//    if(len<=pageremain)
//    {
//    pageremain=len;//不大於256個字節
//    }
//    while(1)
//    {
//    Megain_SPI_Flash_Write_Page(address,pageremain,buf);
//    if(len==pageremain)
//    {
//        buf=0;
//        break;//寫入結束了
//    }
//    else //NumByteToWrite>pageremain
//    {
//        buf = buf + pageremain;
//        address = address + pageremain;             //數據地址偏移
//
//        len = len - pageremain;                  //減去已經寫入了的字節數
//        if(len>128)
//        {
//            pageremain=128;  //一次可以寫入256個字節
//        }
//        else
//        {
//          pageremain=len;     //不夠256個字節了
//        }
//    }
//    }
//}
void Megain_SPI_Flash_Write_NoCheck(unsigned int address, unsigned short  int len, unsigned char *buf)
{
    unsigned short int pageremain;
    pageremain=256-address%256; //單頁剩餘的字節數
    if(len<=pageremain)
    {
      pageremain=len;//不大於256個字節
    }
    while(1)
    {
      Megain_SPI_Flash_Write_Page(address,pageremain,buf);
      if(len==pageremain)
      {
          buf=0;
          break;//寫入結束了
      }
      else //NumByteToWrite>pageremain
      {
          buf = buf + pageremain;
          address = address + pageremain;             //數據地址偏移
          len = len - pageremain;                  //減去已經寫入了的字節數
          if(len>128)
          {
              pageremain=128;  //一次可以寫入256個字節
          }
          else
          {
            pageremain=len;     //不夠256個字節了
          }
      }
    }
}
//寫SPI FLASH
//在指定地址開始寫入指定長度的數據
//該函數帶擦除操作!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)
unsigned char W25Q16_BUFFER[4096];
void W25Q16_Write(unsigned char *pBuffer,unsigned int WriteAddr,unsigned  short int NumByteToWrite)
{
      unsigned int secpos;
      unsigned short int secoff;
      unsigned short int secremain;
      unsigned short int i;
      unsigned char *W25Q16_BUF;
      W25Q16_BUF=W25Q16_BUFFER;
      secpos=WriteAddr/4096;//扇區地址
      secoff=WriteAddr%4096;//在扇區內的偏移
      secremain=4096-secoff;//扇區剩餘空間大小
      //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//測試用
      if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大於4096個字節
      while(1)
      {
            Megain_SPIFlash_Read(secpos*4096,4096,W25Q16_BUF);
            //W25QXX_Read(W25Q16_BUF,secpos*4096,4096);//讀出整個扇區的內容
            for(i=0;i<secremain;i++)//校驗數據
            {
                  if(W25Q16_BUF[secoff+i]!=0XFF)break;//需要擦除
            }
            if(i<secremain)//需要擦除
            {
                  Megain_SPIFlash_EraseSector(secpos,4096);//擦除這個扇區
                  for(i=0;i<secremain;i++)         //複製
                  {
                        W25Q16_BUF[i+secoff]=pBuffer[i];
                  }
                  //W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//寫入整個扇區
                  Megain_SPI_Flash_Write_NoCheck(secpos*4096,4096,W25Q16_BUF);
            }else  Megain_SPI_Flash_Write_NoCheck(WriteAddr,secremain,pBuffer);//寫已經擦除了的,直接寫入扇區剩餘區間.
            if(NumByteToWrite==secremain)break;//寫入結束了
            else//寫入未結束
            {
                  secpos++;//扇區地址增1
                  secoff=0;//偏移位置爲0
                   pBuffer+=secremain;  //指針偏移
                  WriteAddr+=secremain;//寫地址偏移
                   NumByteToWrite-=secremain;                      //字節數遞減
                  if(NumByteToWrite>4096)secremain=4096;    //下一個扇區還是寫不完
                  else secremain=NumByteToWrite;                  //下一個扇區可以寫完了
            }
      };
}

在MG_SPI_Flash.h中添加以下代碼(W25Q16U驅動相關函數聲明)

#ifndef _MG_SPI_FLASH_H
#define _MG_SPI_FLASH_H
#include "app_config.h"
//CS 引腳定義
#define MG_CS_PIN GPIO_PD6
extern bool Megain_SPIFlash_ReadID();
extern void Megain_SPIFlash_ReleasePowerDown();
extern void Megain_SPIFlash_PowerDown();
extern bool Megain_SPIFlash_EraseSector(unsigned int address, unsigned  int len);
extern void Megain_SPIFlash_EraseChip();
extern bool Megain_SPIFlash_Read(unsigned int address, unsigned int len,  unsigned char *buf);
extern bool Megain_SPIFlash_Write(unsigned int address, unsigned char  len, unsigned char *buf);
extern unsigned char Megain_SPIFlash_Init();
extern void W25Q16_Write(unsigned char* pBuffer,unsigned int  WriteAddr,unsigned short int NumByteToWrite);
extern void Megain_SPI_Flash_Write_NoCheck(unsigned int address,  unsigned short int len, unsigned char *buf);
extern void Megain_SPI_Flash_Write_Page(unsigned int address ,unsigned  short int len, unsigned char *buf);
#endif

C.在app.c中的user_init函數中添加以下代碼(測試W25Q16U)

  unsigned char work_buf[4096];
      for(i = 0; i<4096 ;i++)
      {
            work_buf[i] = 0xA0;
      }
      for(i = 0; i<4096 ;i++)
      {
            printf("data[%d] is :%d\r\n",i,work_buf[i]);
      }
      Megain_SPIFlash_Init();
      Megain_SPIFlash_EraseSector(0x00001000,4096);
      W25Q16_Write(work_buf,0x00001000,4096);
      for(i = 0; i<4096 ;i++)
      {
            work_buf[i] = 0;
      }
      Megain_SPIFlash_Read(0x00001000,4096,work_buf);
      for(i = 0; i<4096 ;i++)
      {
            printf("data[%d] is :%d\r\n",i,work_buf[i]);
      }

3、現象

燒錄至板子後,串口成功打印出寫入W25Q16U的數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章