//写SPI FLASH
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
u8 W25QXX_BUFFER[4096]; //先定义一个Buffer用来存储读出来的一个扇区里的数据。
void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) //入口参数:Buffer的地址指针, 要写的地址和数据。
{
u32 secpos;
u16 secoff;
u16 secremain;
u16 i;
u8 * W25QXX_BUF;
W25QXX_BUF=W25QXX_BUFFER;
secpos=WriteAddr/4096;//算出来扇区地址
secoff=WriteAddr@96;//取余数,算出在扇区内的偏移
secremain=4096-secoff;//扇区剩余空间大小
if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//如果要写的数据不大于4096个字节,没 有跨扇区
while(1)
{
W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容,保存在Buffer中。
for(i=0;i 《 secremain;i++) //校验数据
{
if(W25QXX_BUF[secoff+i]!=0XFF)break;//如果有不等于0xFF的数据,就需要擦除
}
if(i 《 secremain)//需要擦除
{
W25QXX_Erase_Sector(secpos); //擦除这个扇区
for(i=0;i 《 secremain;i++) //更新缓存中的数据
{
W25QXX_BUF[ secoff + i ]=pBuffer[i]; //这里的pBuffer中是我们要写的数据,把这些数据更新到缓存中对应的 位置
}
W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//重新写入整个扇区
}else W25QXX_Write_NoCheck(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; //下一个扇区可以写完了
}
};
}
|