找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3046|回复: 2
收起左侧

GPIO模拟驱动W25Q16 FLASH源程序

[复制链接]
ID:46925 发表于 2019-8-21 15:24 | 显示全部楼层 |阅读模式
GPIO模拟驱动W25Q16 FLASH
程序代码应用到产品,非常稳定

源程序如下:
  1. #include "_cpus.h"
  2. #include "_coms.h"

  3. /*=====================================================================================================================*/

  4. //SPI模式:CPOL=1 CPHA=1  CS Active low
  5. //clock is high when inactive
  6. //Data is valid on clock trailing edge
  7. //不活动时,时钟为高 也就是数据可改变区
  8. //数据在时钟后沿有效 数据作用点
  9. #define ENTER_CRITICAL()  
  10.       
  11. #define EXIT_CRITICAL()  
  12.                            
  13. #define MOSI PC6
  14. #define SPSCK PC7
  15. #define ADD_EN_WP PC8
  16. #define MISO PC9
  17. #define SS PC10
  18.                            
  19. #define SS_OUT_L  b_hGpioOut(SS,0)
  20. #define SS_OUT_H  b_hGpioOut(SS,1)
  21.                            
  22. #define WP_OUT_L  b_hGpioOut(ADD_EN_WP,0)                           
  23. #define WP_OUT_H  b_hGpioOut(ADD_EN_WP,1)   

  24. #define SPI_CLK   b_hGpioOut(SPSCK,0);b_dNOP();b_dNOP();b_dNOP();b_dNOP();b_dNOP();b_hGpioOut(SPSCK,1);//和EE相位相反
  25. #define Flash_CS_0  b_hGpioOut(SPSCK,1); ENTER_CRITICAL();WP_OUT_H;SS_OUT_L;
  26. #define Flash_CS_1  WP_OUT_L;SS_OUT_H;EXIT_CRITICAL();     b_hGpioOut(SPSCK,0);

  27.                           

  28.   

  29. void b_hExFlashSetChip2NomlPower(void);
  30. extern void b_hExFlashInit(void)
  31. {
  32.      b_hGpioInit(SS,eOUT_PUSH_PULL,1);
  33.      b_hGpioInit(SPSCK,eOUT_PUSH_PULL,0);
  34.      b_hGpioInit(MOSI,eOUT_PUSH_PULL,0);
  35.      b_hGpioInit(MISO,eOUT_PUSH_PULL,0);
  36.      
  37.      b_hGpioInit(ADD_EN_WP,eOUT_PUSH_PULL,0);
  38.      b_hExFlashSetChip2NomlPower();
  39. }


  40. /*****************************************************************
  41. ** function name  :         SPISendByte
  42. ** description    :  SPI1 send one byte
  43. ** input parameter:  byte to be sent
  44. ** return         :         byte received
  45. ******************************************************************/
  46. static uint08_t ExFlash_hSendByte(uint08_t b)
  47. {
  48.      //时钟低到高输出,高到低输入
  49.      //将b写到ee中,返回数据写到f中
  50.      uint8_t i,f;
  51.      f=0;   
  52.      // b_hGpioOut(SS,0);
  53.      //SPI_SDI_DDR = IOisIN;

  54.      b_hGpioInit(MISO,eIN_PULL_UP,0);
  55.      
  56.      //h_bGpioInit(SPSCK,eOUT_PUSH_PULL,0);
  57.      //h_bGpioInit(MOSI,eOUT_PUSH_PULL,0);
  58.      //SPI_SDI_UP=1; SPI_SCK_UP=1; SPI_SDO_UP=1;
  59.      for(i=8;i;i--)
  60.      {
  61.        //TicksDelayMs(1);
  62.        if(b&bit7){
  63.          // SPI_SDO_ODR=1;        /*向ee写1输出1p4.3*/   
  64.          b_hGpioOut(MOSI,1);
  65.        }else{       
  66.          //SPI_SDO_ODR=0;          /*向ee写0*/
  67.          b_hGpioOut(MOSI,0);
  68.        }
  69.           SPI_CLK;         
  70. //       b_hGpioOut(SPSCK,0);              //低到高跳变时钟
  71. //       TicksDelayMs(1);
  72. //       b_hGpioOut(SPSCK,1);
  73. //       TicksDelayMs(1);
  74.           b<<=1;
  75.           f<<=1;
  76.           if(b_hGpioRead(MISO))f|=bit0;     /*接收数据*/
  77.      }
  78.     // SPI_SDO_UP=0; SPI_SCK_UP=0;SPI_SDI_DDR = IOisOUT;SPI_SDI_ODR= IOisLOW;SPI_SDI_UP=0;
  79.      b_hGpioInit(MISO,eOUT_PUSH_PULL,0);

  80.      //b_hGpioOut(SS,1);
  81.      return f;
  82. }

  83. /*****************************************************************
  84. ** function name  :         SPIReceiveByte
  85. ** description    :  SPI1 receive byte
  86. ** input parameter:  none
  87. ** return         :         byte received
  88. ******************************************************************/
  89. static uint08_t ExFlash_hReceiveByte(void)
  90. {
  91.      uint8_t i,f, b=0xff;;
  92.      f=0;   
  93.     // b_hGpioOut(SS,0);
  94.     // SPI_SDI_DDR = IOisIN;        SPI_SDI_UP=1; SPI_SCK_UP=1; SPI_SDO_UP=1;

  95.       b_hGpioInit(MISO,eIN_PULL_UP,0);
  96.      
  97.      for(i=8;i;i--)
  98.      {
  99.           if(b&bit7)
  100.               b_hGpioOut(MOSI,1);   
  101.           else       
  102.                b_hGpioOut(MOSI,0);
  103.            SPI_CLK;  
  104. //          b_hGpioOut(SPSCK,0);
  105. //          TicksDelayMs(1);
  106. //          b_hGpioOut(SPSCK,1);
  107. //          TicksDelayMs(1);
  108.           b<<=1;
  109.           f<<=1;
  110.           if(b_hGpioRead(MISO))f|=bit0;   
  111.      }
  112.       b_hGpioInit(MISO,eOUT_PUSH_PULL,0);

  113.     // b_hGpioOut(SS,1);
  114.      return f;
  115. }

  116. /******************************************
  117. ** 函 数 名:WriteEnable
  118. ** 功能描述:写使能
  119. ** 参    数:无
  120. ** 返    回:无
  121. *******************************************/
  122. static void ExFlash_hWriteEnable(void)
  123. {
  124.      
  125.      Flash_CS_0;                     
  126.      ExFlash_hSendByte(0x06);//写使能
  127.      Flash_CS_1;

  128. }

  129. static void ExFlash_hWriteDisable( void )
  130. {
  131.      Flash_CS_0;                     
  132.      ExFlash_hSendByte(0x04);//写禁能
  133.      Flash_CS_1;
  134. }


  135. /******************************************************************************/
  136. /* 函数名称:uint8 check_flash_busy(void)                                     */
  137. /* 功能描述:检查flash是否忙                                                  */
  138. /* 参数说明:无                                                               */
  139. /* 参数返回: 如果忙返回1,不忙返回0                                           */
  140. /******************************************************************************/
  141. extern uint08_t b_hExFlashCheckBusy(void)
  142. {
  143.      uint08_t busy_flag;
  144.      Flash_CS_0;
  145.      ExFlash_hSendByte(0x05);
  146.      busy_flag=ExFlash_hReceiveByte();
  147.      Flash_CS_1;                          
  148.      if(busy_flag & 0x03)
  149.           busy_flag = 1;
  150.      else
  151.           busy_flag = 0;
  152.      
  153.      return busy_flag;              
  154. }


  155. extern uint16_t ExFlash_hReadStateReg1_2( void )
  156. {
  157.      uint16_t temp_state;
  158.      
  159.      Flash_CS_0;  
  160.      temp_state=ExFlash_hSendByte(0x05);
  161.      temp_state=temp_state<<8;
  162.      temp_state=temp_state+ExFlash_hSendByte(0x35);
  163.      Flash_CS_1;
  164.      
  165.      return temp_state;
  166.      
  167. }

  168. extern void ExFlash_hWriteStateReg1_2( uint08_t highS,uint08_t lowS)
  169. {
  170.       
  171.      ExFlash_hWriteEnable();
  172.      Flash_CS_0;
  173.      ExFlash_hSendByte(0x01);//send write state regster cmd
  174.      ExFlash_hSendByte(lowS);
  175.      ExFlash_hSendByte(highS);
  176.      Flash_CS_1;
  177.      ExFlash_hWriteDisable();
  178.      
  179. }

  180. /******************************************************************************
  181. ** 函 数 名:ExFlash_hPageProgram                              
  182. ** 功能描述: 向指定的地址写入指定数量的字节                                                                 
  183. ** 参    数:数据缓冲区,字节数,FLASH起始地址                             
  184. ** 返    回:无                       
  185. ******************************************************************************/
  186. extern void ExFlash_hFlashProgram(uint08_t *databuffer,uint32_t address,uint32_t datasize)
  187. {
  188.      ExFlash_hWriteEnable();                                                //写使能
  189.      Flash_CS_0;                                              //置cs低选中
  190.      ExFlash_hSendByte(0x02);
  191.      ExFlash_hSendByte((uint08_t)(address>>16));
  192.      ExFlash_hSendByte((uint08_t)(address>>8));
  193.      ExFlash_hSendByte((uint08_t)address);
  194.      while(datasize>0)
  195.      {
  196.           ExFlash_hSendByte(*databuffer);
  197.           databuffer++;
  198.           datasize--;
  199.      }
  200.      Flash_CS_1;                                              //置cs高不选中
  201.      while(b_hExFlashCheckBusy());                       //等待器件写完结束
  202.      
  203. }

  204. /********************************************
  205. **函 数 名:ReadUniqueID
  206. **功能描述:读取芯片唯一ID号,总共8字节
  207. **参    数:数据缓冲区
  208. *********************************************/
  209. extern void ExFlash_hReadUniqueID(uint08_t *databuffer)
  210. {
  211.      uint08_t i;
  212.      // EnterNoInt();
  213.      Flash_CS_0;                     //置cs低选中
  214.      ExFlash_hSendByte(0x4B);
  215.      ExFlash_hSendByte(0xff);     //这里发送的三个字节是任意的,不一定是0xff
  216.      ExFlash_hSendByte(0xff);
  217.      ExFlash_hSendByte(0xff);
  218.      ExFlash_hSendByte(0xff);
  219.      for(i=0;i<8;i++)
  220.      {
  221.           *databuffer=ExFlash_hReceiveByte();
  222.           databuffer++;
  223.      }
  224.      Flash_CS_1;
  225.      // ExitNoInt();
  226. }


  227. /********************************************************
  228. ** 函 数 名:SectorErase
  229. ** 功能描述:扇区擦除
  230. ** 参    数:扇区地址
  231. ** 返    回:无  
  232. *********************************************************/
  233. void ExFlash_hSector4KErase(uint32_t sector4kN)
  234. {
  235.      //  b_dDI();
  236.      sector4kN*=4096;
  237.      ExFlash_hWriteEnable();                                                //写使能
  238.      Flash_CS_0;                                              //置cs低选中
  239.      ExFlash_hSendByte(0x20);
  240.      ExFlash_hSendByte((uint08_t)(sector4kN>>16));
  241.      ExFlash_hSendByte((uint08_t)(sector4kN>>8));
  242.      ExFlash_hSendByte((uint08_t)sector4kN);
  243.      Flash_CS_1;                                              //置cs高不选中
  244.      //  while(b_hExFlashCheckBusy());                       //等待器件写完结束
  245.      //  EI;
  246. }     

  247. extern void b_hExFlashSector4KEraseAddr(uint32_t sectorAddr)
  248. {
  249.      //b_dDI();
  250.      ExFlash_hWriteEnable();                                                //写使能
  251.      Flash_CS_0;                                              //置cs低选中
  252.      ExFlash_hSendByte(0x20);
  253.      ExFlash_hSendByte((uint08_t)(sectorAddr>>16));
  254.      ExFlash_hSendByte((uint08_t)(sectorAddr>>8));
  255.      ExFlash_hSendByte((uint08_t)sectorAddr);
  256.      Flash_CS_1;                                              //置cs高不选中
  257.      //while(b_hExFlashCheckBusy());                       //等待器件写完结束
  258.      // EI;
  259. }   

  260. void ExFlash_hBlock32KErase(uint32_t sector32kN)
  261. {
  262.      //   b_dDI();
  263.      sector32kN*=131072;
  264.      ExFlash_hWriteEnable();                                //写使能
  265.      Flash_CS_0;                                              //置cs低选中
  266.      ExFlash_hSendByte(0x52);
  267.      ExFlash_hSendByte((uint08_t)(sector32kN>>16));
  268.      ExFlash_hSendByte((uint08_t)(sector32kN>>8));
  269.      ExFlash_hSendByte((uint08_t)sector32kN);
  270.      Flash_CS_1;                                              //置cs高不选中
  271.      //   while(b_hExFlashCheckBusy());                       //等待器件写完结束
  272.      //   EI;
  273. }

  274. void ExFlash_hBlock64KErase(uint32_t address)
  275. {
  276.      //     b_dDI();
  277.      ExFlash_hWriteEnable();                                                //写使能
  278.      Flash_CS_0;                                              //置cs低选中
  279.      ExFlash_hSendByte(0xD8);
  280.      ExFlash_hSendByte((uint08_t)(address>>16));
  281.      ExFlash_hSendByte((uint08_t)(address>>8));
  282.      ExFlash_hSendByte((uint08_t)address);
  283.      Flash_CS_1;                                              //置cs高不选中
  284.      //   while(b_hExFlashCheckBusy());                       //等待器件写完结束
  285.      //   EI;
  286. }

  287. void ExFlash_hAllChipErase(void)
  288. {
  289.      //    b_dDI();
  290.      ExFlash_hWriteEnable();                                                //写使能
  291.      Flash_CS_0;                                              //置cs低选中
  292.      ExFlash_hSendByte(0xC7);
  293.      Flash_CS_1;                                              //置cs高不选中
  294.      //  while(b_hExFlashCheckBusy());                       //等待器件写完结束
  295.      //  EI;
  296. }

  297. extern void b_hExFlashSetChip2LowPower(void)
  298. {
  299.      //   b_dDI();
  300.      ExFlash_hWriteEnable();                                                //写使能
  301.      Flash_CS_0;                                              //置cs低选中
  302.      ExFlash_hSendByte(0xB9);
  303.      Flash_CS_1;                                              //置cs高不选中
  304.      //   while(b_hExFlashCheckBusy());                       //等待器件写完结束
  305.      //   EI;
  306. }

  307. extern void ExFlash_hSetChip2HighPower(void)
  308. {
  309.      //   b_dDI();
  310.      ExFlash_hWriteEnable();                                                //写使能
  311.      Flash_CS_0;                                              //置cs低选中
  312.      ExFlash_hSendByte(0xA3);
  313.      Flash_CS_1;                                              //置cs高不选中
  314.      //   while(b_hExFlashCheckBusy());                       //等待器件写完结束
  315.      //   EI;
  316. }

  317. void b_hExFlashSetChip2NomlPower(void)
  318. {
  319.      ExFlash_hWriteEnable();                                                //写使能
  320.      Flash_CS_0;                                              //置cs低选中
  321.      ExFlash_hSendByte(0xAB);
  322.      Flash_CS_1;                                              //置cs高不选中
  323.      ExFlash_hWriteDisable();
  324.     // while(b_hExFlashCheckBusy());//FDW去掉的
  325.      //  EI;
  326. }
  327. /*****************************************************************
  328. ** 函 数 名:ReadRFlash
  329. ** 功能描述:从指定的地址读取指定数量的字节
  330. ** 参    数:数据缓冲区,字节数,起始地址
  331. ** 返    回:无
  332. ******************************************************************/
  333. extern void b_hExFlashRead(uint08_t *databuffer,uint32_t address,uint16_t datasize)
  334. {   
  335.      uint16_t i;
  336.      //    b_dDI();
  337.      //while( b_hExFlashCheckBusy());
  338.      Flash_CS_0;
  339.      ExFlash_hSendByte(0x03);
  340.      ExFlash_hSendByte((uint08_t)(address>>16));
  341.      ExFlash_hSendByte((uint08_t)(address>>8));
  342.      ExFlash_hSendByte((uint08_t)address);  
  343.      for(i=0;i<datasize;i++)
  344.      {
  345.           databuffer[i]=ExFlash_hReceiveByte();
  346.      }  
  347.      Flash_CS_1;                 //置cs高不选中
  348.      //    EI;
  349. }   

  350. /**************************************************************************
  351. ** 函数名:CheckData
  352. ** 功能描述:检验指定的Flash起始地址的数据和指定的缓冲区的数据是否全部相等
  353. ** 参数:数据缓冲区DataBuffer, Flash起始地址DataAddr,数据字节数
  354. ** 返回:全部相同返回1,否则返回0
  355. ***************************************************************************/
  356. extern uint8_t ExFlash_hCheckData(uint08_t *DataBuffer, uint32_t DataAddr, uint16_t DataSize)
  357. {
  358.      uint08_t data;
  359.      uint16_t i;
  360.      for(i=0;i<DataSize;i++)
  361.      {
  362.           b_hExFlashRead(&data,1,DataAddr+i);
  363.           if(data!=DataBuffer[i])return 0;
  364.      }
  365.      return 1;
  366. }



  367. //extern void ExFlash_mWDataToSector(uint08_t *pDataBuffer,uint16_t dataSize, uint08_t sector)
  368. //{
  369. //  
  370. //      uint08_t
  371. //      for(uint16_t i=0;i<dataSize;i++)//校验数据
  372. //      {
  373. //              if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除            
  374. //      }
  375. //}
  376. //无检验写SPI FLASH
  377. //必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
  378. //具有自动换页功能
  379. //在指定地址开始写入指定长度的数据,但是要确保地址不越界!
  380. //pBuffer:数据存储区
  381. //WriteAddr:开始写入的地址(24bit)
  382. //NumByteToWrite:要写入的字节数(最大65535)
  383. //CHECK OK
  384. extern void ExFlash_hWriteMustErase(uint08_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
  385. {                                           
  386.      uint16_t pageremain;          
  387.      pageremain=256-WriteAddr%256; //单页剩余的字节数                             
  388.      if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
  389.      while(1)
  390.      {         
  391.           ExFlash_hFlashProgram(pBuffer,WriteAddr,pageremain);
  392.           if(NumByteToWrite==pageremain)break;//写入结束了
  393.           else //NumByteToWrite>pageremain
  394.           {
  395.                pBuffer+=pageremain;
  396.                WriteAddr+=pageremain;       
  397.                
  398.                NumByteToWrite-=pageremain;                          //减去已经写入了的字节数
  399.                if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
  400.                else pageremain=NumByteToWrite;           //不够256个字节了
  401.           }
  402.      };            
  403. }

  404. //写SPI FLASH  
  405. //在指定地址开始写入指定长度的数据
  406. //该函数带擦除操作!
  407. //pBuffer:数据存储区
  408. //WriteAddr:开始写入的地址(24bit)
  409. //NumByteToWrite:要写入的字节数(最大65535)                    


  410. //屏敝注解掉此随机写SPI_FLASH函数,
  411. //原因:资源消耗大--需要栈空间要调设到  4096+0x200  测试时用的是 0x2200的栈空间
  412. //void ExFlash_hWrite(uint08_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
  413. //{
  414. //      static uint32_t secpos;
  415. //        uint16_t secoff;
  416. //        uint16_t secremain;          
  417. //         uint16_t i;  
  418. //        uint08_t SPI_FLASH_BUF[4096];
  419. //  
  420. //
  421. //        secpos=WriteAddr/4096;//起始地址所在扇区号  地址 0~511 for w25x16
  422. //        secoff=WriteAddr%4096;//起始地址所在扇区号的偏移 在扇区内的偏移
  423. //        secremain=4096-secoff;//起始地址所在扇区剩余空间大小   
  424. //
  425. //        
  426. //        if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节  装的下
  427. //        while(1)
  428. //        {       
  429. //                b_hExFlashRead(SPI_FLASH_BUF,secpos*4096,4096);//读出整个扇区的内容
  430. //                for(i=0;i<secremain;i++)//校验数据
  431. //                {
  432. //                        if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除            
  433. //                }
  434. //                if(i<secremain)//需要擦除
  435. //                {
  436. //                        ExFlash_hSector4KErase(secpos);//擦除这个扇区
  437. //                        for(i=0;i<secremain;i++)           //复制
  438. //                        {
  439. //                                SPI_FLASH_BUF[i+secoff]=pBuffer[i];          
  440. //                        }
  441. //                        ExFlash_hWriteMustErase(SPI_FLASH_BUF,secpos*4096,4096);//写入整个扇区  
  442. //
  443. //                }else ExFlash_hWriteMustErase(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.
  444. //               
  445. //                if(NumByteToWrite==secremain)break;//写入结束了
  446. //                else//写入未结束
  447. //                {
  448. //                        secpos++;//扇区地址增1
  449. //                        secoff=0;//偏移位置为0          
  450. //
  451. //                           pBuffer+=secremain;  //指针偏移
  452. //                        WriteAddr+=secremain;//写地址偏移          
  453. //                           NumByteToWrite-=secremain;                                //字节数递减
  454. //                        if(NumByteToWrite>4096)secremain=4096;        //下一个扇区还是写不完
  455. //                        else secremain=NumByteToWrite;                        //下一个扇区可以写完了
  456. //                }         
  457. //        };                  
  458. //}
  459. extern void b_hExFlashWrite(uint08_t *databuffer,uint32_t address,uint32_t datasize)
  460. {
  461.      ExFlash_hWriteEnable();                                                //写使能
  462.      Flash_CS_0;                                               //置cs低选中
  463.      ExFlash_hSendByte(0x02);
  464.      ExFlash_hSendByte((uint08_t)(address>>16));
  465.      ExFlash_hSendByte((uint08_t)(address>>8));
  466.      ExFlash_hSendByte((uint08_t)address);
  467.      while(datasize>0)
  468.      {
  469.           ExFlash_hSendByte(*databuffer);
  470.           databuffer++;
  471.           datasize--;
  472.      }
  473.      Flash_CS_1;                                           //置cs高不选中
  474.                       //等待器件写完结束
  475.      
  476. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:46925 发表于 2019-8-21 15:26 | 显示全部楼层
自已顶一下,有需要的拿走
回复

使用道具 举报

ID:163476 发表于 2023-3-12 23:56 | 显示全部楼层
感谢分享,回头试试
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表