GPIO模擬驅動W25Q16 FLASH
程序代碼應用到產品,非常穩定
源程序如下:- #include "_cpus.h"
- #include "_coms.h"
- /*=====================================================================================================================*/
- //SPI模式:CPOL=1 CPHA=1 CS Active low
- //clock is high when inactive
- //Data is valid on clock trailing edge
- //不活動時,時鐘為高 也就是數據可改變區
- //數據在時鐘后沿有效 數據作用點
- #define ENTER_CRITICAL()
-
- #define EXIT_CRITICAL()
-
- #define MOSI PC6
- #define SPSCK PC7
- #define ADD_EN_WP PC8
- #define MISO PC9
- #define SS PC10
-
- #define SS_OUT_L b_hGpioOut(SS,0)
- #define SS_OUT_H b_hGpioOut(SS,1)
-
- #define WP_OUT_L b_hGpioOut(ADD_EN_WP,0)
- #define WP_OUT_H b_hGpioOut(ADD_EN_WP,1)
- #define SPI_CLK b_hGpioOut(SPSCK,0);b_dNOP();b_dNOP();b_dNOP();b_dNOP();b_dNOP();b_hGpioOut(SPSCK,1);//和EE相位相反
- #define Flash_CS_0 b_hGpioOut(SPSCK,1); ENTER_CRITICAL();WP_OUT_H;SS_OUT_L;
- #define Flash_CS_1 WP_OUT_L;SS_OUT_H;EXIT_CRITICAL(); b_hGpioOut(SPSCK,0);
-
-
- void b_hExFlashSetChip2NomlPower(void);
- extern void b_hExFlashInit(void)
- {
- b_hGpioInit(SS,eOUT_PUSH_PULL,1);
- b_hGpioInit(SPSCK,eOUT_PUSH_PULL,0);
- b_hGpioInit(MOSI,eOUT_PUSH_PULL,0);
- b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
-
- b_hGpioInit(ADD_EN_WP,eOUT_PUSH_PULL,0);
- b_hExFlashSetChip2NomlPower();
- }
- /*****************************************************************
- ** function name : SPISendByte
- ** description : SPI1 send one byte
- ** input parameter: byte to be sent
- ** return : byte received
- ******************************************************************/
- static uint08_t ExFlash_hSendByte(uint08_t b)
- {
- //時鐘低到高輸出,高到低輸入
- //將b寫到ee中,返回數據寫到f中
- uint8_t i,f;
- f=0;
- // b_hGpioOut(SS,0);
- //SPI_SDI_DDR = IOisIN;
- b_hGpioInit(MISO,eIN_PULL_UP,0);
-
- //h_bGpioInit(SPSCK,eOUT_PUSH_PULL,0);
- //h_bGpioInit(MOSI,eOUT_PUSH_PULL,0);
- //SPI_SDI_UP=1; SPI_SCK_UP=1; SPI_SDO_UP=1;
- for(i=8;i;i--)
- {
- //TicksDelayMs(1);
- if(b&bit7){
- // SPI_SDO_ODR=1; /*向ee寫1輸出1p4.3*/
- b_hGpioOut(MOSI,1);
- }else{
- //SPI_SDO_ODR=0; /*向ee寫0*/
- b_hGpioOut(MOSI,0);
- }
- SPI_CLK;
- // b_hGpioOut(SPSCK,0); //低到高跳變時鐘
- // TicksDelayMs(1);
- // b_hGpioOut(SPSCK,1);
- // TicksDelayMs(1);
- b<<=1;
- f<<=1;
- if(b_hGpioRead(MISO))f|=bit0; /*接收數據*/
- }
- // SPI_SDO_UP=0; SPI_SCK_UP=0;SPI_SDI_DDR = IOisOUT;SPI_SDI_ODR= IOisLOW;SPI_SDI_UP=0;
- b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
- //b_hGpioOut(SS,1);
- return f;
- }
- /*****************************************************************
- ** function name : SPIReceiveByte
- ** description : SPI1 receive byte
- ** input parameter: none
- ** return : byte received
- ******************************************************************/
- static uint08_t ExFlash_hReceiveByte(void)
- {
- uint8_t i,f, b=0xff;;
- f=0;
- // b_hGpioOut(SS,0);
- // SPI_SDI_DDR = IOisIN; SPI_SDI_UP=1; SPI_SCK_UP=1; SPI_SDO_UP=1;
- b_hGpioInit(MISO,eIN_PULL_UP,0);
-
- for(i=8;i;i--)
- {
- if(b&bit7)
- b_hGpioOut(MOSI,1);
- else
- b_hGpioOut(MOSI,0);
- SPI_CLK;
- // b_hGpioOut(SPSCK,0);
- // TicksDelayMs(1);
- // b_hGpioOut(SPSCK,1);
- // TicksDelayMs(1);
- b<<=1;
- f<<=1;
- if(b_hGpioRead(MISO))f|=bit0;
- }
- b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
- // b_hGpioOut(SS,1);
- return f;
- }
- /******************************************
- ** 函 數 名:WriteEnable
- ** 功能描述:寫使能
- ** 參 數:無
- ** 返 回:無
- *******************************************/
- static void ExFlash_hWriteEnable(void)
- {
-
- Flash_CS_0;
- ExFlash_hSendByte(0x06);//寫使能
- Flash_CS_1;
-
- }
- static void ExFlash_hWriteDisable( void )
- {
- Flash_CS_0;
- ExFlash_hSendByte(0x04);//寫禁能
- Flash_CS_1;
- }
- /******************************************************************************/
- /* 函數名稱:uint8 check_flash_busy(void) */
- /* 功能描述:檢查flash是否忙 */
- /* 參數說明:無 */
- /* 參數返回: 如果忙返回1,不忙返回0 */
- /******************************************************************************/
- extern uint08_t b_hExFlashCheckBusy(void)
- {
- uint08_t busy_flag;
- Flash_CS_0;
- ExFlash_hSendByte(0x05);
- busy_flag=ExFlash_hReceiveByte();
- Flash_CS_1;
- if(busy_flag & 0x03)
- busy_flag = 1;
- else
- busy_flag = 0;
-
- return busy_flag;
- }
- extern uint16_t ExFlash_hReadStateReg1_2( void )
- {
- uint16_t temp_state;
-
- Flash_CS_0;
- temp_state=ExFlash_hSendByte(0x05);
- temp_state=temp_state<<8;
- temp_state=temp_state+ExFlash_hSendByte(0x35);
- Flash_CS_1;
-
- return temp_state;
-
- }
- extern void ExFlash_hWriteStateReg1_2( uint08_t highS,uint08_t lowS)
- {
-
- ExFlash_hWriteEnable();
- Flash_CS_0;
- ExFlash_hSendByte(0x01);//send write state regster cmd
- ExFlash_hSendByte(lowS);
- ExFlash_hSendByte(highS);
- Flash_CS_1;
- ExFlash_hWriteDisable();
-
- }
- /******************************************************************************
- ** 函 數 名:ExFlash_hPageProgram
- ** 功能描述: 向指定的地址寫入指定數量的字節
- ** 參 數:數據緩沖區,字節數,FLASH起始地址
- ** 返 回:無
- ******************************************************************************/
- extern void ExFlash_hFlashProgram(uint08_t *databuffer,uint32_t address,uint32_t datasize)
- {
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0x02);
- ExFlash_hSendByte((uint08_t)(address>>16));
- ExFlash_hSendByte((uint08_t)(address>>8));
- ExFlash_hSendByte((uint08_t)address);
- while(datasize>0)
- {
- ExFlash_hSendByte(*databuffer);
- databuffer++;
- datasize--;
- }
- Flash_CS_1; //置cs高不選中
- while(b_hExFlashCheckBusy()); //等待器件寫完結束
-
- }
- /********************************************
- **函 數 名:ReadUniqueID
- **功能描述:讀取芯片唯一ID號,總共8字節
- **參 數:數據緩沖區
- *********************************************/
- extern void ExFlash_hReadUniqueID(uint08_t *databuffer)
- {
- uint08_t i;
- // EnterNoInt();
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0x4B);
- ExFlash_hSendByte(0xff); //這里發送的三個字節是任意的,不一定是0xff
- ExFlash_hSendByte(0xff);
- ExFlash_hSendByte(0xff);
- ExFlash_hSendByte(0xff);
- for(i=0;i<8;i++)
- {
- *databuffer=ExFlash_hReceiveByte();
- databuffer++;
- }
- Flash_CS_1;
- // ExitNoInt();
- }
- /********************************************************
- ** 函 數 名:SectorErase
- ** 功能描述:扇區擦除
- ** 參 數:扇區地址
- ** 返 回:無
- *********************************************************/
- void ExFlash_hSector4KErase(uint32_t sector4kN)
- {
- // b_dDI();
- sector4kN*=4096;
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0x20);
- ExFlash_hSendByte((uint08_t)(sector4kN>>16));
- ExFlash_hSendByte((uint08_t)(sector4kN>>8));
- ExFlash_hSendByte((uint08_t)sector4kN);
- Flash_CS_1; //置cs高不選中
- // while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- extern void b_hExFlashSector4KEraseAddr(uint32_t sectorAddr)
- {
- //b_dDI();
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0x20);
- ExFlash_hSendByte((uint08_t)(sectorAddr>>16));
- ExFlash_hSendByte((uint08_t)(sectorAddr>>8));
- ExFlash_hSendByte((uint08_t)sectorAddr);
- Flash_CS_1; //置cs高不選中
- //while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- void ExFlash_hBlock32KErase(uint32_t sector32kN)
- {
- // b_dDI();
- sector32kN*=131072;
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0x52);
- ExFlash_hSendByte((uint08_t)(sector32kN>>16));
- ExFlash_hSendByte((uint08_t)(sector32kN>>8));
- ExFlash_hSendByte((uint08_t)sector32kN);
- Flash_CS_1; //置cs高不選中
- // while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- void ExFlash_hBlock64KErase(uint32_t address)
- {
- // b_dDI();
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0xD8);
- ExFlash_hSendByte((uint08_t)(address>>16));
- ExFlash_hSendByte((uint08_t)(address>>8));
- ExFlash_hSendByte((uint08_t)address);
- Flash_CS_1; //置cs高不選中
- // while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- void ExFlash_hAllChipErase(void)
- {
- // b_dDI();
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0xC7);
- Flash_CS_1; //置cs高不選中
- // while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- extern void b_hExFlashSetChip2LowPower(void)
- {
- // b_dDI();
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0xB9);
- Flash_CS_1; //置cs高不選中
- // while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- extern void ExFlash_hSetChip2HighPower(void)
- {
- // b_dDI();
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0xA3);
- Flash_CS_1; //置cs高不選中
- // while(b_hExFlashCheckBusy()); //等待器件寫完結束
- // EI;
- }
- void b_hExFlashSetChip2NomlPower(void)
- {
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0xAB);
- Flash_CS_1; //置cs高不選中
- ExFlash_hWriteDisable();
- // while(b_hExFlashCheckBusy());//FDW去掉的
- // EI;
- }
- /*****************************************************************
- ** 函 數 名:ReadRFlash
- ** 功能描述:從指定的地址讀取指定數量的字節
- ** 參 數:數據緩沖區,字節數,起始地址
- ** 返 回:無
- ******************************************************************/
- extern void b_hExFlashRead(uint08_t *databuffer,uint32_t address,uint16_t datasize)
- {
- uint16_t i;
- // b_dDI();
- //while( b_hExFlashCheckBusy());
- Flash_CS_0;
- ExFlash_hSendByte(0x03);
- ExFlash_hSendByte((uint08_t)(address>>16));
- ExFlash_hSendByte((uint08_t)(address>>8));
- ExFlash_hSendByte((uint08_t)address);
- for(i=0;i<datasize;i++)
- {
- databuffer[i]=ExFlash_hReceiveByte();
- }
- Flash_CS_1; //置cs高不選中
- // EI;
- }
- /**************************************************************************
- ** 函數名:CheckData
- ** 功能描述:檢驗指定的Flash起始地址的數據和指定的緩沖區的數據是否全部相等
- ** 參數:數據緩沖區DataBuffer, Flash起始地址DataAddr,數據字節數
- ** 返回:全部相同返回1,否則返回0
- ***************************************************************************/
- extern uint8_t ExFlash_hCheckData(uint08_t *DataBuffer, uint32_t DataAddr, uint16_t DataSize)
- {
- uint08_t data;
- uint16_t i;
- for(i=0;i<DataSize;i++)
- {
- b_hExFlashRead(&data,1,DataAddr+i);
- if(data!=DataBuffer[i])return 0;
- }
- return 1;
- }
- //extern void ExFlash_mWDataToSector(uint08_t *pDataBuffer,uint16_t dataSize, uint08_t sector)
- //{
- //
- // uint08_t
- // for(uint16_t i=0;i<dataSize;i++)//校驗數據
- // {
- // if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除
- // }
- //}
- //無檢驗寫SPI FLASH
- //必須確保所寫的地址范圍內的數據全部為0XFF,否則在非0XFF處寫入的數據將失敗!
- //具有自動換頁功能
- //在指定地址開始寫入指定長度的數據,但是要確保地址不越界!
- //pBuffer:數據存儲區
- //WriteAddr:開始寫入的地址(24bit)
- //NumByteToWrite:要寫入的字節數(最大65535)
- //CHECK OK
- extern void ExFlash_hWriteMustErase(uint08_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
- {
- uint16_t pageremain;
- pageremain=256-WriteAddr%256; //單頁剩余的字節數
- if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256個字節
- while(1)
- {
- ExFlash_hFlashProgram(pBuffer,WriteAddr,pageremain);
- if(NumByteToWrite==pageremain)break;//寫入結束了
- else //NumByteToWrite>pageremain
- {
- pBuffer+=pageremain;
- WriteAddr+=pageremain;
-
- NumByteToWrite-=pageremain; //減去已經寫入了的字節數
- if(NumByteToWrite>256)pageremain=256; //一次可以寫入256個字節
- else pageremain=NumByteToWrite; //不夠256個字節了
- }
- };
- }
- //寫SPI FLASH
- //在指定地址開始寫入指定長度的數據
- //該函數帶擦除操作!
- //pBuffer:數據存儲區
- //WriteAddr:開始寫入的地址(24bit)
- //NumByteToWrite:要寫入的字節數(最大65535)
- //屏敝注解掉此隨機寫SPI_FLASH函數,
- //原因:資源消耗大--需要棧空間要調設到 4096+0x200 測試時用的是 0x2200的棧空間
- //void ExFlash_hWrite(uint08_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
- //{
- // static uint32_t secpos;
- // uint16_t secoff;
- // uint16_t secremain;
- // uint16_t i;
- // uint08_t SPI_FLASH_BUF[4096];
- //
- //
- // secpos=WriteAddr/4096;//起始地址所在扇區號 地址 0~511 for w25x16
- // secoff=WriteAddr%4096;//起始地址所在扇區號的偏移 在扇區內的偏移
- // secremain=4096-secoff;//起始地址所在扇區剩余空間大小
- //
- //
- // if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096個字節 裝的下
- // while(1)
- // {
- // b_hExFlashRead(SPI_FLASH_BUF,secpos*4096,4096);//讀出整個扇區的內容
- // for(i=0;i<secremain;i++)//校驗數據
- // {
- // if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除
- // }
- // if(i<secremain)//需要擦除
- // {
- // ExFlash_hSector4KErase(secpos);//擦除這個扇區
- // for(i=0;i<secremain;i++) //復制
- // {
- // SPI_FLASH_BUF[i+secoff]=pBuffer[i];
- // }
- // ExFlash_hWriteMustErase(SPI_FLASH_BUF,secpos*4096,4096);//寫入整個扇區
- //
- // }else ExFlash_hWriteMustErase(pBuffer,WriteAddr,secremain);//寫已經擦除了的,直接寫入扇區剩余區間.
- //
- // if(NumByteToWrite==secremain)break;//寫入結束了
- // else//寫入未結束
- // {
- // secpos++;//扇區地址增1
- // secoff=0;//偏移位置為0
- //
- // pBuffer+=secremain; //指針偏移
- // WriteAddr+=secremain;//寫地址偏移
- // NumByteToWrite-=secremain; //字節數遞減
- // if(NumByteToWrite>4096)secremain=4096; //下一個扇區還是寫不完
- // else secremain=NumByteToWrite; //下一個扇區可以寫完了
- // }
- // };
- //}
- extern void b_hExFlashWrite(uint08_t *databuffer,uint32_t address,uint32_t datasize)
- {
- ExFlash_hWriteEnable(); //寫使能
- Flash_CS_0; //置cs低選中
- ExFlash_hSendByte(0x02);
- ExFlash_hSendByte((uint08_t)(address>>16));
- ExFlash_hSendByte((uint08_t)(address>>8));
- ExFlash_hSendByte((uint08_t)address);
- while(datasize>0)
- {
- ExFlash_hSendByte(*databuffer);
- databuffer++;
- datasize--;
- }
- Flash_CS_1; //置cs高不選中
- //等待器件寫完結束
-
- }
復制代碼
|