Flash的读写基本操作过程:
1.unlock FLASH 解锁
2.擦除指定的页(查看工程空间分布,以防擦除程序本身)
3.写入数据
4.读出数据效验
5:注意FLASH_ProgramWord(uint32_t Address, uint32_t Data); 写入32位数据,4个字节,每页2048/4=512,地址每次+4写入读出
6:注意FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);写入16为数据,2个字节,每页2048/2=1024地址每次+2写入读出,还需留意把32位数据强制转化为vu16*(地址)写入读出,简单表述就是把32位分成了两个16位分别写入.
7:注意定义数组和运行代码在RAM存储中的空间,占用空间过多,就会导致溢满提醒
u16 STMFLASH_BUF[STM_SECTOR_SIZE / 2];
u32 FLASH_BUFDATA[STM_SECTOR_SIZE];
uint32_t FLASH_DATASIZE[STM_SECTOR_SIZE/4];
单页32位数据写入
/*单页32位数据写入*/
int InternalFlsah_Test(void)
{
uint32_t *p;
uint32_t EraseCounter = 0x00; //记录擦除的页数
uint32_t Address = 0x00; //记录写入的地址
uint32_t Data = 0x3210ABCD; //记录写入的数据
uint32_t NbrOfPage = 0x00; //记录写入的页数
FLASH_Status FLASH_Status = FLASH_COMPLETE; //记录擦除的结果
TestStatus MemoryProgramStatus = PASSED;
//解锁
FLASH_Unlock();
//计算要擦除的页数
NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
//清楚所有标志位
FLASH_ClearFlag(FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_EOP);
//按页擦除
for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASH_Status == FLASH_COMPLETE);EraseCounter++)
{
FLASH_Status = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
}
//向FLASH内部写入数据
Address = WRITE_START_ADDR;
while ((Address < WRITE_END_ADDR) && (FLASH_Status == FLASH_COMPLETE))
{
FLASH_Status = FLASH_ProgramWord(Address, Data);
Address = Address + 4;
}
FLASH_Lock();
//写入检查
Address = WRITE_START_ADDR;
while((Address < WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
{
if((*(__IO uint32_t*)Address) != Data)
{
MemoryProgramStatus = FAILED;
}
Address +=4;
}
return MemoryProgramStatus;
}
跨页16位数据写入FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
//读取指定地址的半字(16位数据)
//faddr:读地址(此地址必须为2的倍数!!)
//返回值:对应数据.
u16 STM32FLASH_ReadHalfWord(u32 faddr)
{
return *(vu16*)faddr;
}
//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToRead:半字(16位)数
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)
{
u16 i;
for(i=0;i<NumToRead;i++)
{
pBuffer[i]= STM32FLASH_ReadHalfWord(ReadAddr);
ReadAddr += 2;
}
}
//WriteAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u16 i;
for(i=0;i<NumToWrite;i++)
{
FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);
WriteAddr+=2;
}
}
//从指定地址开始写入指定长度的数据
//WriteAddr:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针
//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u32 secpos; //第几页
u16 secoff; //页内偏移地址
u16 secremain; //页内剩余地址
u16 i;
u32 offaddr; //相对flash基地址0x08000000偏移了地址量
if((WriteAddr < STM32_FLASJ_BASE) || (WriteAddr>=(STM32_FLASJ_BASE + 1024*STM32_FLASH_SIZE)))return; //非法地址
//解锁
FLASH_Unlock();
offaddr = WriteAddr - STM32_FLASJ_BASE; //flash基地址偏移了多少地址
secpos = offaddr / STM_SECTOR_SIZE; //所在起始页
secoff = (offaddr % STM_SECTOR_SIZE) / 2; //在该页内偏移地址 即是在第几个u16 数据上(2 是读取和写入的字节是u16)
secremain = FLASH_PAGE_SIZE /2 - secoff; //该页内剩余的空间大小
if(NumToWrite <= secremain)secremain=NumToWrite;//写入的数据没超过当前页内剩余的空间
while(1)
{
STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASJ_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整页
for(i=0;i<secremain;i++) //判断是否需要擦除
{
if(STMFLASH_BUF[secoff+i]!=0xFFFF) break;
}
if(i<secremain) //需要擦除
{
FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASJ_BASE);
for(i=0;i<secremain;i++)
{
STMFLASH_BUF[i+secoff] = pBuffer[i];
}
STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASJ_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
}
else //不需要擦除
{
STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);
}
if(NumToWrite == secremain) //没有跨页写入
{
break;//写入结束跳出循环
}
else //有跨页写入,增加新页
{
secpos++; //页地址加1
secoff = 0; //页内偏移地址为0
pBuffer+=secremain;//指针偏移
WriteAddr+=secremain;//写地址偏移
NumToWrite -= secremain;//剩余要写入的字节(16位)数递减
if(NumToWrite>(STM_SECTOR_SIZE / 2))
{
secremain=STM_SECTOR_SIZE / 2; //新页还是写不完
}
else
{
secremain = NumToWrite; //新页可以写完了
}
}
}
FLASH_Lock();
}
跨页32位写入数据_FLASH_ProgramWord(uint32_t Address, uint32_t Data)
void ARMFLASH_READ(uint32_t Address,uint32_t *pData,uint32_t Flsah_Number)
{
uint32_t i;
uint32_t *pz;
for(i = 0; i<Flsah_Number;i++)
{
pz = (uint32_t *)Address;
pData[i] = *pz;
Address+=4;
}
}
void Internal_FLASH(uint32_t Address,uint32_t *Data,uint32_t Number)
{
u32 i ;
uint32_t *p;
uint32_t Page_setoff; //页内偏移地址
uint32_t Page_Residue; //页内剩余地址
uint32_t Page_Num; //页数(第几页)
// uint32_t Flash_setoff; //相比较Flash偏移地址
uint32_t Write_Address;
Page_setoff =( (Address - STM32_FLASJ_BASE) %STM_SECTOR_SIZE)/4;
Page_Residue =STM32_FLASH_SIZE - Page_setoff ;
Page_Num = (Address - STM32_FLASJ_BASE) / STM_SECTOR_SIZE;
if(Address<STM32_FLASJ_BASE || Address > (STM_SECTOR_SIZE*STM32_FLASH_SIZE+STM32_FLASJ_BASE))return;
FLASH_Unlock();
if(Page_Residue > Number) Page_Residue = Number;
while (1)
{
ARMFLASH_READ(Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE ,FLASH_DATASIZE,STM_SECTOR_SIZE/4);
for ( i = 0; i < Page_Residue; i++)
{
if(FLASH_DATASIZE[Page_setoff+i]!=0xFFFF)
{
break;
}
}
if(i<Page_Residue)
{
FLASH_ErasePage(Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE );
Write_Address = Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE;
for(i=0;i<Page_Residue;i++)
{
FLASH_ProgramWord(Write_Address,Data[i]);
p = (uint32_t *)Write_Address;
Write_Address+=4 ;
}
}
else
{
for(i=0;i<Page_Residue;i++)
{
Write_Address = Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE;
FLASH_ProgramWord(Address,Data[i]);
Write_Address+=4;
}
}
if(Number == Page_Residue)
{
break;
}
else
{
Page_Num++;
Page_setoff = 0;
Data += Page_Residue;
Address += Page_Residue;
Number -= Page_Residue;
if(Number>(STM_SECTOR_SIZE/4))
{
Page_Residue = STM_SECTOR_SIZE/4; //新页未完
}
else
{
Page_Residue = Number; //新页写完
}
}
}
FLASH_Lock();
}
主程序
u32 flash_rx_buff[5000];//读取flash内容存放到该数组
u32 flash_rx_len =5000;
u32 flash_tx_buff[5000];//读取flash内容存放到该数组
u32 flash_tx_len =5000;
u16 flash1_rx_buff[5000];//读取flash内容存放到该数组
u16 flash1_rx_len = 5000;
u16 flash1_tx_buff[5000];//读取flash内容存放到该数组
u16 flash1_tx_len = 5000;
int main(void)
{
uint32_t *p;
u32 x = 0x01;
u32 t = 0;
uint32_t Address123;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级组
uart_init(115200); //串口初始化为115200
for(t=0;t<flash_tx_len;t++)
{
flash_tx_buff[t] = x;
x++;
}
Internal_FLASH(WRITE_START_ADDR1,flash_tx_buff,flash_tx_len);
Address123 =WRITE_START_ADDR1;
for(t=0;t<flash_tx_len;t++)
{
p = (uint32_t *)Address123;
Address123+=4;
printf("%0x: ",*p);
}
while(1)
{
}
}