当前位置: 代码迷 >> 综合 >> FLASH写入出错问题记录
  详细解决方案

FLASH写入出错问题记录

热度:12   发布时间:2024-02-02 00:45:23.0

一、按页写入函数 ,不可跨页,根据地址写入

注意:地址+写入字节数 跨页了会写入出错!!!

/*******************************************************************************
*名称:SPI_Flash_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
*输入:pBuffer        :数据存储区WriteAddr      :开始写入的地址NumByteToWrite :要写入的字节数(最大256),不可超过该页剩余字节数
*输出:pBuffer 数据存储区
*返回:无
*功能:在指定地址开始写入最大256字节的数据
*说明:SPI在一页(0~16384)内写入少于256个字节的数据
*******************************************************************************/	 					
void SPI_Flash_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{uint16_t i;SPI_Flash_Wait_Busy();SPI_FLASH_Write_Enable();                  //使能写操作 //SPI_FLASH_Write_unProtect();W25Qxx_CS_LOW();                           //使能器件   SPI_ReadWriteByte(SPI1,W25X_PageProgram);      //发送写页命令   SPI_ReadWriteByte(SPI1,(uint8_t)((WriteAddr)>>16)); //发送24bit地址    SPI_ReadWriteByte(SPI1,(uint8_t)((WriteAddr)>>8));   SPI_ReadWriteByte(SPI1,(uint8_t)WriteAddr); if(NumByteToWrite > SPI_FLASH_PerWritePageSize){NumByteToWrite = SPI_FLASH_PerWritePageSize;}for(i=0;i<NumByteToWrite;i++)				//循环写数SPI_ReadWriteByte(SPI1,pBuffer[i]);			  W25Qxx_CS_HIGH();							//取消片选 SPI_Flash_Wait_Busy();						//等待写入结束
} 

 

二、按地址写入函数 ,自动换页写入,不校验数据,不带擦除功能

写入前要确保该地址bit位数据为 1

/*****************************************
//无检验写SPI FLASH
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
//CHECK OK
******************************************/
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{uint16_t pageremain;pageremain=256-WriteAddr%256; //单页剩余的字节数if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节while(1){SPI_Flash_Write_Page(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个字节了}}; }

 

三、按地址写入函数 ,自动换页写入,带擦除功能

该函数会校验从写入地址到扇区尾的数据是否为0xFF,不是0xFF则先擦除扇区

/*****************************************
//写SPI FLASH
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
******************************************/
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{uint32_t secpos;uint16_t secoff;uint16_t secremain;uint16_t i;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;i<secremain;i++)//校验数据{if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除}if(i<secremain)//需要擦除{SPI_Flash_Erase_Sector(secpos*4096);	//擦除这个扇区for(i=0;i<secremain;i++)		//复制{W25QXX_BUF[i+secoff]=pBuffer[i];}W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.if(NumByteToWrite==secremain)break;//写入结束了else//写入未结束{secpos++;					//扇区地址增1secoff=0;					//偏移位置为0pBuffer+=secremain; 		//指针偏移WriteAddr+=secremain;		//写地址偏移NumByteToWrite-=secremain;	//字节数递减if(NumByteToWrite>4096)secremain=4096;	//下一个扇区还是写不完else secremain=NumByteToWrite;			//下一个扇区可以写完了}};
}

 

  相关解决方案