一、按页写入函数 ,不可跨页,根据地址写入
注意:地址+写入字节数 跨页了会写入出错!!!
/*******************************************************************************
*名称: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; //下一个扇区可以写完了}};
}