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高不选中
- //等待器件写完结束
-
- }
复制代码
|