讨教一下~STM32驱动w25q64fv遇到32K,64K擦除不完全的问题?

2019-12-22 13:48发布

        前些天淘宝购得30只w25q64fviq芯片,1.9元/只.直接替换掉原来红牛板上的SST25VF016B,花了些功夫终于成功了.
例子是将BMP图片写入SPI_Flash中,再读取SPI_Flash中的图片显示在LCD屏上,由于之前是2M_Byte,现在是8M_Byte,想测试一下8M空间,于是改写了测试程序.
方案是:
        首先将Flash写入地址定义到0页的0x000000,擦除写入230454 Byte的图片,读出显示.
然后首地址按4KB增加,循环擦除写入230454 Byte的图片,读出显示.

擦除程序会根据写入数据的大小计算,采用最佳方式来擦除(64K,32K,4K).
        由于BMP图片大小是:        230454 Byte,按最小4K擦除块方式,需要擦除228K的空间.
按最佳方案应该是:228K = 3次*64K擦除 + 1次*32K擦除 +1次*4K擦除.
结果现在问题来了:
        图片第一次擦除写入读出显示没有问题,接着第二次以后的会出现图片花屏现象,而且多出现在后半屏花屏,
已经确定是没有正常擦除造成的,于是在擦除子程序中取消了64K,32K的擦除操作,只采用4K擦除方式.结果正常.
经反复验证,无论是64K+4K擦除方案或是32K+4K擦除方案,都不正常.

不知道有没有人遇到过这样的问题,特来请教一下是那里出了问题???


3.png (340.79 KB, 下载次数: 0) 下载附件 2016-4-22 04:23 上传

  1. /*******************************************************************************
  2. * Function Name  : SSTF016B_WR
  3. * Description    : SST25VF016B的写函数,可写1个和多个数据到指定地址
  4. * Input          : - Dst: 目标地址,范围 0x0 - MAX_ADDR(MAX_ADDR = 0x1FFFFF)
  5. *                  - SndbufPt: 发送缓存区指针
  6. *                  - NByte: 要写的数据字节数
  7. * Output         : None
  8. * Return         : 操作成功则返回OK,失败则返回ERROR
  9. * Attention                 : 若某功能下,某一入口参数无效,可在该入口参数处填Invalid,该参数将被忽略
  10. *******************************************************************************/
  11. uint8_t SSTF016B_WR(uint32_t Dst, uint8_t* SndbufPt,uint32_t NByte)
  12. {
  13. //        uint8_t temp = 0,temp1 = 0,StatRgVal = 0;//
  14.         uint32_t i = 0;
  15.         //------------------------------------------------------------------------------------------
  16.         if (( (Dst+NByte-1 > MAX_ADDR)||(NByte == 0) ))
  17.         {
  18.                 return (ERROR);         /*        检查入口参数 */
  19.         }
  20.         //------------------------------------------------------------------------------------------

  21.         #if 0        //--取消下面的读取状态寄存器操作
  22.         SPI_FLASH_CS_LOW();                                 
  23.         Flash_ReadWriteByte(0x05);                                                            /* 发送读状态寄存器1命令        */
  24.         temp = Flash_ReadWriteByte(0xFF);                                            /* 保存读得的状态寄存器值 */
  25.         SPI_FLASH_CS_HIGH();

  26.         SPI_FLASH_CS_LOW();                                 
  27.         Flash_ReadWriteByte(0x35);                                                            /* 发送读状态寄存器2命令        */
  28.         temp1 = Flash_ReadWriteByte(0xFF);                                            /* 保存读得的状态寄存器值 */
  29.         SPI_FLASH_CS_HIGH();       

  30.         SPI_FLASH_CS_LOW();                               
  31.         Flash_ReadWriteByte(0x50);                                                            /* 使状态寄存器可写        */
  32.         SPI_FLASH_CS_HIGH();       
  33.                
  34.         SPI_FLASH_CS_LOW();                               
  35.         Flash_ReadWriteByte(0x01);                                                            /* 发送写状态寄存器指令 */
  36.         Flash_ReadWriteByte(0);                                                                    /* 清0BPx位,使Flash芯片全区可写 */
  37.         Flash_ReadWriteByte(temp1);                                                                /* 清0BPx位,使Flash芯片全区可写 */
  38.         SPI_FLASH_CS_HIGH();
  39.        
  40.         SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */                       
  41.         #endif
  42.        
  43.         //------------------------------------------------------------------------------------------
  44.         for(i = 0; i < NByte; i++)
  45.         {
  46.                 SPI_FLASH_CS_LOW();                               
  47.                 Flash_ReadWriteByte(0x06);                                                    /* 发送写使能命令 */
  48.                 SPI_FLASH_CS_HIGH();                       

  49.                 SPI_FLASH_CS_LOW();                                       
  50.                 Flash_ReadWriteByte(0x02);                                                     /* 发送字节数据烧写命令        */
  51.                 Flash_ReadWriteByte((((Dst+i) & 0xFFFFFF) >> 16));  /* 发送3个字节的地址信息 */
  52.                 Flash_ReadWriteByte((((Dst+i) & 0xFFFF) >> 8));
  53.                 Flash_ReadWriteByte((Dst+i) & 0xFF);
  54.                 Flash_ReadWriteByte(SndbufPt[i]);                                        /* 发送被烧写的数据        */
  55.                 SPI_FLASH_CS_HIGH();                       
  56.                 SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  57.         }
  58.         //------------------------------------------------------------------------------------------
  59.         #if 0        //--取消下面的恢复状态寄存器操作
  60.         SPI_FLASH_CS_LOW();                                       
  61.         Flash_ReadWriteByte(0x06);                                                            /* 发送写使能命令 */
  62.         SPI_FLASH_CS_HIGH();                       

  63.         SPI_FLASH_CS_LOW();                                       
  64.         Flash_ReadWriteByte(0x50);                                                            /* 使状态寄存器可写        */
  65.         SPI_FLASH_CS_HIGH();
  66.                        
  67.         SPI_FLASH_CS_LOW();                               
  68.         Flash_ReadWriteByte(0x01);                                                            /* 发送写状态寄存器指令 */
  69.         Flash_ReadWriteByte(temp);                                                             /* 恢复状态寄存器设置信息 */
  70.         Flash_ReadWriteByte(temp1);                                                             /* 恢复状态寄存器设置信息 */
  71.         SPI_FLASH_CS_HIGH();
  72.         SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  73.         #endif
  74.         //------------------------------------------------------------------------------------------

  75.         return (ENABLE);               
  76. }
复制代码
  1. <p>/*******************************************************************************
  2. * Function Name  : SSTF016B_Erase
  3. * Description    : 根据指定的扇区号选取最高效的算法擦除
  4. * Input          : - sec1: 起始扇区号,范围(0~511)
  5. *                  - sec2: 终止扇区号,范围(0~511)
  6. * Output         : None
  7. * Return         : 操作成功则返回OK,失败则返回ERROR
  8. * Attention                 : None
  9. *******************************************************************************/
  10. uint8_t SSTF016B_Erase(uint32_t sec1, uint32_t sec2)
  11. {
  12.         uint8_t  ErCount,temp2 = 0;
  13. //        uint8_t  temp0 = 0,temp1 = 0;//
  14.     uint32_t sectorStartAddr = 0;                                 
  15.         uint32_t sectorNumber = 0;                                                               /* 要擦除的扇区数目 */
  16.         uint32_t CurSecNumber = 0;                                                              /* 当前要擦除的扇区号 */
  17.        
  18.         /*  检查入口参数 */
  19.         if ((sec1 > SEC_MAX)||(sec2 > SEC_MAX))       
  20.         {
  21.                 return (ERROR);       
  22.         }
  23.         //------------------------------------------------------------------------------------------
  24.            #if 0        //--取消下面的读取状态寄存器操作
  25.            SPI_FLASH_CS_LOW();                         
  26.         Flash_ReadWriteByte(0x05);                                                                /* 发送读状态寄存器1命令        */
  27.         temp0 = Flash_ReadWriteByte(0xFF);                                                /* 保存读得的状态寄存器值 */
  28.         SPI_FLASH_CS_HIGH();

  29.            SPI_FLASH_CS_LOW();                         
  30.         Flash_ReadWriteByte(0x35);                                                                /* 发送读状态寄存器2命令        */
  31.         temp1 = Flash_ReadWriteByte(0xFF);                                                /* 保存读得的状态寄存器值 */
  32.         SPI_FLASH_CS_HIGH();       

  33.         SPI_FLASH_CS_LOW();                       
  34.         Flash_ReadWriteByte(0x50);                                                                /* 使状态寄存器可写        */
  35.         SPI_FLASH_CS_HIGH();                       

  36.         SPI_FLASH_CS_LOW();                                                                         
  37.         Flash_ReadWriteByte(0x01);                                                                /* 发送写状态寄存器指令        */
  38.         Flash_ReadWriteByte(0);                                                                        /* 清0BPx位,使Flash芯片全区可写 */
  39.         Flash_ReadWriteByte(temp1);                                                                /* 清0BPx位,使Flash芯片全区可写 */
  40.         SPI_FLASH_CS_HIGH();
  41.        
  42.         SPI_FLASH_CS_LOW();                       
  43.         Flash_ReadWriteByte(0x06);                                                                /* 发送写使能命令 */
  44.         SPI_FLASH_CS_HIGH();
  45.         SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */                               
  46.         #endif
  47.         //------------------------------------------------------------------------------------------
  48.         /* 如果用户输入的起始扇区号大于终止扇区号,则在内部作出调整 */
  49.         if (sec1 > sec2)
  50.         {
  51.            temp2 = sec1;
  52.            sec1  = sec2;
  53.            sec2  = temp2;
  54.         }
  55.         /* 若起止扇区号相等则擦除单个扇区 */
  56.         if (sec1 == sec2)       
  57.         {
  58.                 SPI_FLASH_CS_LOW();                               
  59.                 Flash_ReadWriteByte(0x06);                                                    /* 发送写使能命令 */
  60.                 SPI_FLASH_CS_HIGH();                       

  61.             sectorStartAddr = SEC_SIZE * sec1;                                          /* 计算扇区的起始地址        */
  62.             SPI_FLASH_CS_LOW();       
  63.             Flash_ReadWriteByte(0x20);                                                                          /* 发送扇区擦除指令 */
  64.             Flash_ReadWriteByte(((sectorStartAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
  65.                    Flash_ReadWriteByte(((sectorStartAddr & 0xFFFF) >> 8));
  66.                    Flash_ReadWriteByte(sectorStartAddr & 0xFF);
  67.                   SPI_FLASH_CS_HIGH();
  68.                 SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  69.                 return (ENABLE);                       
  70.         }
  71.         //------------------------------------------------------------------------------------------
  72.        
  73.     /* 根据起始扇区和终止扇区间距调用最快速的擦除功能 */       
  74.        
  75.         if (sec2 - sec1 == SEC_MAX)       
  76.         {
  77.                 SPI_FLASH_CS_LOW();                               
  78.                 Flash_ReadWriteByte(0x06);                                                    /* 发送写使能命令 */
  79.                 SPI_FLASH_CS_HIGH();
  80.                
  81.                 SPI_FLASH_CS_LOW();                       
  82.                 Flash_ReadWriteByte(0xC7);                                                          /* 发送芯片擦除指令(60h or C7h) */
  83.                 SPI_FLASH_CS_HIGH();               
  84.                 SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  85.                    return (ENABLE);
  86.         }
  87.        
  88.         sectorNumber = sec2 - sec1 +1;                                                  /* 获取要擦除的扇区数目 */
  89.         CurSecNumber  = sec1;                                                                      /* 从起始扇区开始擦除        */
  90.         GUI_IntegerText(10,55,CurSecNumber);
  91.         //------------------------------------------------------------------------------------------
  92.         #if 1
  93.         /* 若两个扇区之间的间隔够大,则采取8扇区擦除算法 */
  94.         ErCount = 0;
  95.         while (sectorNumber >= 16)
  96.         {
  97.                 SPI_FLASH_CS_LOW();                               
  98.                 Flash_ReadWriteByte(0x06);                                                    /* 发送写使能命令 */
  99.                 SPI_FLASH_CS_HIGH();                       

  100.             sectorStartAddr = SEC_SIZE * CurSecNumber;                          /* 计算扇区的起始地址 */
  101.             SPI_FLASH_CS_LOW();       
  102.             Flash_ReadWriteByte(0xd8);                                                          /* 发送64KB擦除指令 */
  103.             Flash_ReadWriteByte(((sectorStartAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
  104.                    Flash_ReadWriteByte(((sectorStartAddr & 0xFFFF) >> 8));
  105.                    Flash_ReadWriteByte(sectorStartAddr & 0xFF);
  106.                   SPI_FLASH_CS_HIGH();       
  107.                 SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  108.                 CurSecNumber  += 16;
  109.                 sectorNumber -=  16;
  110.                 GUI_IntegerText(59,55,++ErCount);
  111.         }
  112.         #endif
  113.         //------------------------------------------------------------------------------------------
  114.         #if 1
  115.         /* 若两个扇区之间的间隔够大,则采取8扇区擦除算法 */
  116.         ErCount = 0;
  117.         while (sectorNumber >= 8)
  118.         {
  119.                 SPI_FLASH_CS_LOW();                               
  120.                 Flash_ReadWriteByte(0x06);                                                    /* 发送写使能命令 */
  121.                 SPI_FLASH_CS_HIGH();                       

  122.             sectorStartAddr = SEC_SIZE * CurSecNumber;                                  /* 计算扇区的起始地址 */
  123.             SPI_FLASH_CS_LOW();       
  124.             Flash_ReadWriteByte(0x52);                                                          /* 发送32KB擦除指令 */
  125.             Flash_ReadWriteByte(((sectorStartAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
  126.                    Flash_ReadWriteByte(((sectorStartAddr & 0xFFFF) >> 8));
  127.                    Flash_ReadWriteByte(sectorStartAddr & 0xFF);
  128.                   SPI_FLASH_CS_HIGH();       
  129.                 SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  130.                 CurSecNumber  += 8;
  131.                 sectorNumber -=  8;
  132.                 GUI_IntegerText(114,55,++ErCount);
  133.         }
  134.         #endif
  135.         //------------------------------------------------------------------------------------------
  136.         /* 采用扇区擦除算法擦除剩余的扇区 */
  137.         ErCount = 0;
  138.         while (sectorNumber >= 1)
  139.         {
  140.                 SPI_FLASH_CS_LOW();                               
  141.                 Flash_ReadWriteByte(0x06);                                                    /* 发送写使能命令 */
  142.                 SPI_FLASH_CS_HIGH();                       

  143.             sectorStartAddr = SEC_SIZE * CurSecNumber;                                  /* 计算扇区的起始地址 */
  144.             SPI_FLASH_CS_LOW();       
  145.             Flash_ReadWriteByte(0x20);                                                          /* 发送4K扇区擦除指令 */
  146.             Flash_ReadWriteByte(((sectorStartAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
  147.                    Flash_ReadWriteByte(((sectorStartAddr & 0xFFFF) >> 8));
  148.                    Flash_ReadWriteByte(sectorStartAddr & 0xFF);
  149.                   SPI_FLASH_CS_HIGH();
  150.                 SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */       
  151.                 CurSecNumber  += 1;
  152.                 sectorNumber -=  1;
  153.                 GUI_IntegerText(170,55,++ErCount);
  154.         }
  155.         //------------------------------------------------------------------------------------------
  156.         #if 0        //--取消下面的恢复状态寄存器操作
  157.        
  158.     /* 擦除结束,恢复状态寄存器信息 */
  159.         SPI_FLASH_CS_LOW();                       
  160.         Flash_ReadWriteByte(0x06);                                                                  /* 发送写使能命令 */
  161.         SPI_FLASH_CS_HIGH();                       

  162.         SPI_FLASH_CS_LOW();                       
  163.         Flash_ReadWriteByte(0x50);                                                                  /* 使状态寄存器可写 */
  164.         SPI_FLASH_CS_HIGH();
  165.        
  166.         SPI_FLASH_CS_LOW();                       
  167.         Flash_ReadWriteByte(0x01);                                                                  /* 发送写状态寄存器指令 */
  168.         Flash_ReadWriteByte(temp0);                                                                  /* 恢复状态寄存器设置信息 */
  169.         Flash_ReadWriteByte(temp1);                                                                  /* 恢复状态寄存器设置信息 */
  170.         SPI_FLASH_CS_HIGH();
  171.         SPI_FLASH_WaitForWriteEnd();                                              /* 一直等待,直到芯片空闲        */         
  172.         #endif  
  173.         //------------------------------------------------------------------------------------------
  174.         return (ENABLE);
  175. }</p><p>
  176. </p><p>
  177. </p><p>
  178. </p>
复制代码


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。