新手上路
- 积分
- 44
- 金钱
- 44
- 注册时间
- 2021-1-17
- 在线时间
- 7 小时
|
本帖最后由 入职新手糖糖 于 2021-1-30 22:58 编辑
//SPI在一页内写入少于256个字节的数据 【一页 = 256BYTES】 ,w25q128页的序号:(0~65535)
//在指定地址开始写入最大256字节的数据------------------1页里面写---------------------
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
void W25QXX_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
u16 i;
W25QXX_Write_Enable(); //SET WEL
W25QXX_CS=0; //使能器件
SPI2_ReadWriteByte(W25X_PageProgram); //发送写页命令
SPI2_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址
SPI2_ReadWriteByte((u8)((WriteAddr)>>8));
SPI2_ReadWriteByte((u8)WriteAddr);
for(i=0;i<NumByteToWrite;i++)SPI2_ReadWriteByte(pBuffer);//循环写数
W25QXX_CS=1; //取消片选
W25QXX_Wait_Busy(); //等待写入结束
}
//具有自动换页功能---------------------------跨页写--------------------------------
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535) 64KB=一块
//CHECK OK
void W25QXX_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
u16 pageremain;
pageremain=256-WriteAddr%256; //单页剩余的字节数 WriteAddr%256 -> 地址对1页取余=1页的偏移量
if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
while(1)
{
W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
if(NumByteToWrite==pageremain)break;//写入结束了,呼应上面if的判断
else //NumByteToWrite>pageremain(要写入的字节数 超过 单页剩余的字节数)
{
pBuffer+=pageremain; //下一次写入从数组的pBuffer[pageremain]开始写
WriteAddr+=pageremain; //下一次要写入的地址+pageremain
NumByteToWrite-=pageremain; //减去已经写入了的字节数
if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
else pageremain=NumByteToWrite; //不够256个字节了
}
};
}
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!-------------------------跨sector写--------------------------
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:u16要写入的字节数(最大65535) 64KB=一块(block)
u8 W25QXX_BUFFER[4096]; //一个sector = 4096BYTES
void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
u32 secpos;
u16 secoff;
u16 secremain;
u16 i;
u8 * W25QXX_BUF; //局部变量,用完销毁
W25QXX_BUF=W25QXX_BUFFER;
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)//需要擦除
{
W25QXX_Erase_Sector(secpos); //擦除这个扇区
for(i=0;i<secremain;i++) //复制pBuffer[0--secremain] 到 数组对应扇区的剩余空间
{
W25QXX_BUF[i+secoff]=pBuffer; //数组对应扇区要写入地址【开始写入pBuffer[]里的数据】
}
W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//把数组写入整个扇区[此函数能够跨页写入]
}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.
if(NumByteToWrite==secremain)break;//写入结束了[要写入的数据<=1个扇区的剩余字节]
else//写入未结束
{
secpos++;//扇区地址增1
secoff=0;//偏移位置为0
pBuffer+=secremain; //指针偏移,接下来写入pBuffer[secremain]之后的数据
WriteAddr+=secremain; //写地址偏移,要写入flash的 地址+secremain
NumByteToWrite-=secremain; //字节数递减,剩余要写入的字节数
if(NumByteToWrite>4096)secremain=4096;//下一个扇区还是写不完
else secremain=NumByteToWrite; //下一个扇区可以写完了
}
};
}
|
|