//----------------------------------------------------------------- // ³ÌÐòÃèÊö: // W25QXXÇý¶¯³ÌÐò // ×÷ Õß: ÁèÖǵç×Ó // ¿ªÊ¼ÈÕÆÚ: 2018-08-04 // Íê³ÉÈÕÆÚ: 2018-08-04 // ÐÞ¸ÄÈÕÆÚ: // µ±Ç°°æ±¾: V1.0 // ÀúÊ·°æ±¾: // - V1.0: (2018-08-04)W25QXX³õʼ»¯ºÍÅäÖà // µ÷ÊÔ¹¤¾ß: ÁèÖÇSTM32F429+CycloneIVµç×ÓϵͳÉè¼Æ¿ª·¢°å¡¢LZE_ST_LINK2 // ˵ Ã÷: // //----------------------------------------------------------------- //----------------------------------------------------------------- // Í·Îļþ°üº¬ //----------------------------------------------------------------- #include "w25qxx.h" #include "spi.h" #include "delay.h" //----------------------------------------------------------------- u16 W25QXX_TYPE=W25Q128; // ĬÈÏÊÇW25Q128 //----------------------------------------------------------------- // void W25QXX_Init(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ³õʼ»¯SPI FLASHµÄIO¿Ú // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Init(void) { u8 temp; GPIO_InitTypeDef GPIO_Initure; __HAL_RCC_GPIOG_CLK_ENABLE(); // ʹÄÜGPIOGʱÖÓ GPIO_Initure.Pin=GPIO_PIN_3; // PG3 -> FLASH_CS GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; // ÍÆÍìÊä³ö GPIO_Initure.Pull=GPIO_PULLUP; // ÉÏÀ­ GPIO_Initure.Speed=GPIO_SPEED_FAST; // ¿ìËÙ HAL_GPIO_Init(GPIOG,&GPIO_Initure); // ³õʼ»¯ W25QXX_CS=1; // È¡ÏûƬѡ SPI_Init(); // ³õʼ»¯SPI W25QXX_TYPE=W25QXX_ReadID(); // ¶ÁÈ¡FLASH ID. if(W25QXX_TYPE==W25Q256) // ÈôSPI FLASHΪW25Q256 { temp=W25QXX_ReadSR(3); // ¶Áȡ״̬¼Ä´æÆ÷3£¬ÅжϵØÖ·Ä£Ê½ if((temp&0X01)==0) // Èç¹û²»ÊÇ4×Ö½ÚµØÖ·Ä£Ê½,Ôò½øÈë4×Ö½ÚµØÖ·Ä£Ê½ { W25QXX_CS=0; // Ñ¡ÖÐ SPI1_ReadWriteByte(W25X_Enable4ByteAddr);// ·¢ËͽøÈë4×Ö½ÚµØÖ·Ä£Ê½Ö¸Áî W25QXX_CS=1; // È¡ÏûƬѡ } } } //----------------------------------------------------------------- // u8 W25QXX_ReadSR(u8 regno) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ¶ÁÈ¡W25QXXµÄ״̬¼Ä´æÆ÷£¬W25QXXÒ»¹²ÓÐ3¸ö״̬¼Ä´æÆ÷ // Èë¿Ú²ÎÊý: u8 regno£º×´Ì¬¼Ä´æÆ÷ºÅ£¬·¶Î§:1~3 // ·µ »Ø Öµ: u8 byte£º×´Ì¬¼Ä´æÆ÷Öµ // ×¢ÒâÊÂÏî: ״̬¼Ä´æÆ÷1£º // BIT7 6 5 4 3 2 1 0 // SPR RV TB BP2 BP1 BP0 WEL BUSY // SPR:ĬÈÏ0,״̬¼Ä´æÆ÷±£»¤Î»,ÅäºÏWPʹÓà // TB,BP2,BP1,BP0:FLASHÇøÓòд±£»¤ÉèÖà // WEL:дʹÄÜËø¶¨ // BUSY:æ±ê¼Çλ(1,æ;0,¿ÕÏÐ) // ĬÈÏ:0x00 // ״̬¼Ä´æÆ÷2£º // BIT7 6 5 4 3 2 1 0 // SUS CMP LB3 LB2 LB1 (R) QE SRP1 // ״̬¼Ä´æÆ÷3£º // BIT7 6 5 4 3 2 1 0 // HOLD/RST DRV1 DRV0 (R) (R) WPS ADP ADS // //----------------------------------------------------------------- u8 W25QXX_ReadSR(u8 regno) { u8 byte=0,command=0; switch(regno) { case 1: command=W25X_ReadStatusReg1; // ¶Á״̬¼Ä´æÆ÷1Ö¸Áî break; case 2: command=W25X_ReadStatusReg2; // ¶Á״̬¼Ä´æÆ÷2Ö¸Áî break; case 3: command=W25X_ReadStatusReg3; // ¶Á״̬¼Ä´æÆ÷3Ö¸Áî break; default: command=W25X_ReadStatusReg1; break; } W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(command); // ·¢ËͶÁȡ״̬¼Ä´æÆ÷ÃüÁî byte=SPI1_ReadWriteByte(0Xff); // ¶Áȡһ¸ö×Ö½Ú W25QXX_CS=1; // È¡ÏûƬѡ return byte; } //----------------------------------------------------------------- // void W25QXX_Write_SR(u8 regno,u8 sr) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: дW25QXX״̬¼Ä´æÆ÷ // Èë¿Ú²ÎÊý: u8 regno£º×´Ì¬¼Ä´æÆ÷ºÅ£¬·¶Î§:1~3 // u8 sr£ºÐ´ÈëÒ»¸ö×Ö½Ú // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Write_SR(u8 regno,u8 sr) { u8 command=0; switch(regno) { case 1: command=W25X_WriteStatusReg1; // д״̬¼Ä´æÆ÷1Ö¸Áî break; case 2: command=W25X_WriteStatusReg2; // д״̬¼Ä´æÆ÷2Ö¸Áî break; case 3: command=W25X_WriteStatusReg3; // д״̬¼Ä´æÆ÷3Ö¸Áî break; default: command=W25X_WriteStatusReg1; break; } W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(command); // ·¢ËÍдȡ״̬¼Ä´æÆ÷ÃüÁî SPI1_ReadWriteByte(sr); // дÈëÒ»¸ö×Ö½Ú W25QXX_CS=1; // È¡ÏûƬѡ } //----------------------------------------------------------------- // void W25QXX_Write_Enable(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: W25QXXдʹÄÜ // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Write_Enable(void) { W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_WriteEnable); // ·¢ËÍдʹÄÜ W25QXX_CS=1; // È¡ÏûƬѡ } //----------------------------------------------------------------- // void W25QXX_Write_Disable(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: WW25QXXд½ûÖ¹ // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Write_Disable(void) { W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_WriteDisable); // ·¢ËÍд½ûÖ¹Ö¸Áî W25QXX_CS=1; // È¡ÏûƬѡ } //----------------------------------------------------------------- // u16 W25QXX_ReadID(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ¶ÁȡоƬID // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: u16 Temp£ºÐ¾Æ¬ÐͺŠ// ×¢ÒâÊÂÏî: 0XEF13,±íʾоƬÐͺÅΪW25Q80 // 0XEF14,±íʾоƬÐͺÅΪW25Q16 // 0XEF15,±íʾоƬÐͺÅΪW25Q32 // 0XEF16,±íʾоƬÐͺÅΪW25Q64 // 0XEF17,±íʾоƬÐͺÅΪW25Q128 // 0XEF18,±íʾоƬÐͺÅΪW25Q256 // //----------------------------------------------------------------- u16 W25QXX_ReadID(void) { u16 Temp = 0; W25QXX_CS=0; SPI1_ReadWriteByte(0x90);// ·¢ËͶÁÈ¡IDÃüÁî SPI1_ReadWriteByte(0x00); SPI1_ReadWriteByte(0x00); SPI1_ReadWriteByte(0x00); Temp|=SPI1_ReadWriteByte(0xFF)<<8; Temp|=SPI1_ReadWriteByte(0xFF); W25QXX_CS=1; return Temp; } //----------------------------------------------------------------- // void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ¶ÁÈ¡SPI FLASH£¬ÔÚÖ¸¶¨µØÖ·¿ªÊ¼¶Áȡָ¶¨³¤¶ÈµÄÊý¾Ý // Èë¿Ú²ÎÊý: u8* pBuffer£ºÊý¾Ý´æ´¢Çø // u32 ReadAddr:¿ªÊ¼¶ÁÈ¡µÄµØÖ·(24bit) // u16 NumByteToRead:ª¶ÁÈ¡µÄ×Ö½ÚÊý(×î´ó65535) // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) { u16 i; W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_ReadData); // ·¢ËͶÁÈ¡ÃüÁî if(W25QXX_TYPE==W25Q256) // Èç¹ûÊÇW25Q256µÄ»°µØÖ·Îª4×ֽڵģ¬Òª·¢ËÍ×î¸ß8λ { SPI1_ReadWriteByte((u8)((ReadAddr)>>24)); } SPI1_ReadWriteByte((u8)((ReadAddr)>>16)); // ·¢ËÍ24bitµØÖ· SPI1_ReadWriteByte((u8)((ReadAddr)>>8)); SPI1_ReadWriteByte((u8)ReadAddr); for(i=0;i>24)); } SPI1_ReadWriteByte((u8)((WriteAddr)>>16)); // ·¢ËÍ24bitµØÖ· SPI1_ReadWriteByte((u8)((WriteAddr)>>8)); SPI1_ReadWriteByte((u8)WriteAddr); for(i=0;ipageremain { pBuffer+=pageremain; WriteAddr+=pageremain; NumByteToWrite-=pageremain; // ¼õÈ¥ÒѾ­Ð´ÈëÁ˵Ä×Ö½ÚÊý if(NumByteToWrite>256) pageremain=256; // Ò»´Î¿ÉÒÔдÈë256¸ö×Ö½Ú else pageremain=NumByteToWrite; // ²»¹»256¸ö×Ö½ÚÁË } } } u8 W25QXX_BUFFER[4096]; //----------------------------------------------------------------- // void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: дSPI FLASH // Èë¿Ú²ÎÊý: u8* pBuffer£ºÊý¾Ý´æ´¢Çø // u32 WriteAddr£º¿ªÊ¼Ð´ÈëµÄµØÖ·(24bit) // u16 NumByteToWrite£ºÒªÐ´ÈëµÄ×Ö½ÚÊý(×î´ó65535) // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ¸Ãº¯Êý´ø²Á³ý²Ù×÷! // //----------------------------------------------------------------- void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u32 secpos; u16 secoff; u16 secremain; u16 i; u8 * W25QXX_BUF; W25QXX_BUF=W25QXX_BUFFER; secpos=WriteAddr/4096; // ÉÈÇøµØÖ· secoff=WriteAddr%4096; // ÔÚÉÈÇøÄ򵀮«ÒÆ secremain=4096-secoff; // ÉÈÇøÊ£Óà¿Õ¼ä´óС if(NumByteToWrite<=secremain) secremain=NumByteToWrite;//²»´óÓÚ4096¸ö×Ö½Ú while(1) { W25QXX_Read(W25QXX_BUF,secpos*4096,4096); // ¶Á³öÕû¸öÉÈÇøµÄÄÚÈÝ for(i=0;i4096) secremain=4096; // ÏÂÒ»¸öÉÈÇø»¹ÊÇд²»Íê else secremain=NumByteToWrite; // ÏÂÒ»¸öÉÈÇø¿ÉÒÔдÍêÁË } } } //----------------------------------------------------------------- // void W25QXX_Erase_Chip(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ²Á³ýÕû¸öоƬ // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Erase_Chip(void) { W25QXX_Write_Enable(); // SET WEL W25QXX_Wait_Busy(); W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_ChipErase); // ·¢ËÍÆ¬²Á³ýÃüÁî W25QXX_CS=1; // È¡ÏûƬѡ W25QXX_Wait_Busy(); // µÈ´ýоƬ²Á³ý½áÊø } //----------------------------------------------------------------- // void W25QXX_Erase_Sector(u32 Dst_Addr) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ²Á³ýÒ»¸öÉÈÇø // Èë¿Ú²ÎÊý: u32 Dst_Addr£ºÉÈÇøµØÖ· ¸ù¾Ýʵ¼ÊÈÝÁ¿ÉèÖà // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ²Á³ýÒ»¸öÉÈÇøµÄ×îÉÙʱ¼ä:150ms // //----------------------------------------------------------------- void W25QXX_Erase_Sector(u32 Dst_Addr) { Dst_Addr*=4096; W25QXX_Write_Enable(); // SET WEL W25QXX_Wait_Busy(); W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_SectorErase); // ·¢ËÍÉÈÇø²Á³ýÖ¸Áî if(W25QXX_TYPE==W25Q256) // Èç¹ûÊÇW25Q256µÄ»°µØÖ·Îª4×ֽڵģ¬Òª·¢ËÍ×î¸ß8λ { SPI1_ReadWriteByte((u8)((Dst_Addr)>>24)); } SPI1_ReadWriteByte((u8)((Dst_Addr)>>16)); // ·¢ËÍ24bitµØÖ· SPI1_ReadWriteByte((u8)((Dst_Addr)>>8)); SPI1_ReadWriteByte((u8)Dst_Addr); W25QXX_CS=1; // È¡ÏûƬѡ W25QXX_Wait_Busy(); // µÈ´ý²Á³ýÍê³É } //----------------------------------------------------------------- // void W25QXX_Wait_Busy(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: µÈ´ý¿ÕÏÐ // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_Wait_Busy(void) { while((W25QXX_ReadSR(1)&0x01)==0x01); // µÈ´ýBUSYλÇå¿Õ } //----------------------------------------------------------------- // void W25QXX_PowerDown(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: ½øÈëµôµçģʽ // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_PowerDown(void) { W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_PowerDown); // ·¢Ë͵ôµçÃüÁî W25QXX_CS=1; // È¡ÏûƬѡ delay_us(3); // µÈ´ýTPD } //----------------------------------------------------------------- // void W25QXX_WAKEUP(void) //----------------------------------------------------------------- // // º¯Êý¹¦ÄÜ: »½ÐÑ // Èë¿Ú²ÎÊý: ÎÞ // ·µ »Ø Öµ: ÎÞ // ×¢ÒâÊÂÏî: ÎÞ // //----------------------------------------------------------------- void W25QXX_WAKEUP(void) { W25QXX_CS=0; // ʹÄÜÆ÷¼þ SPI1_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB W25QXX_CS=1; // È¡ÏûƬѡ delay_us(3); // µÈ´ýTRES1 } //----------------------------------------------------------------- // End Of File //-----------------------------------------------------------------