STM32F4 Flash数据的保存和读取。
STM32 F4的存储和F1的存储稍稍有些区别。F4的最小存储单位是扇区,而F1的最小存储单位是页。(那么这样擦除的时候就存在区别,F1系的可以只擦除一页PAGES(最小1K),而F4需要擦除一个扇区SECTORS(最小16K),好处就是F1可以最大程度不影响本扇区非本页的数据,而F4则会影响本扇区数据)
STM32的读取比较简单,直接用指针指向对应的空间地址就可以取数据。最小可以写4个字节,即以字为存储单位。
u32 STMFLASH_ReadWord(u32 faddr)
{
return *(vu32*)faddr;
}
void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)
{
u32 i;
for(i=0;i
{
pBuffer
=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
ReadAddr+=4;//偏移4个字节.
}
}
STM32的写入稍微麻烦一点,需要先把扇区的数据擦除成0XFF,然后才可以写入数据。具体做法如地下:
1.禁止中断
2.flash解锁,禁止数据缓存
3.扇区擦除并检验
4.写入数据
5.开启数据缓存,flash上锁
7.开启中断
uint16_t STMFLASH_GetFlashSector(u32 addr)
{
if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
return FLASH_Sector_11;
}
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)
{
FLASH_Status status = FLASH_COMPLETE;
u32 addrx=0;
u32 endaddr=0;
if(WriteAddr
return; //非法地址
IntsStorage;
StoreDisableInts; //禁止中断
FLASH_Unlock(); //解锁
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存
addrx=WriteAddr; //写入的起始地址
endaddr=WriteAddr+NumToWrite*4; //写入的结束地址
if(addrx<0X1FFF0000) //只有主存储区,才需要执行擦除操作!!
{
while(addrx
{
if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
{
status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!!
if(status!=FLASH_COMPLETE)break; //发生错误了
}else addrx+=4;
}
}
if(status==FLASH_COMPLETE)
{
while(WriteAddr
{
if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据
{
break; //写入异常
}
WriteAddr+=4;
pBuffer++;
}
}
FLASH_DataCacheCmd(ENABLE); //FLASH擦除结束,开启数据缓存
FLASH_Lock();//上锁
RestoreInts; //开启中断
}
所以如果要修改扇区内的数据,则需要先将扇区内的数据取出来,然后修改对应的数据,最后再存入。
以修改一个结构体数据为例,先将数据使用memcpy函数cpy出来,然后使用结构体指向该数据,然后该结构体赋新值,最后再写入数据,这样就不会影响该扇区其他结构体的数据。
void UpdateSystemFuncParaData(struct ElevatorFuncPara *elevator_func_parameter)
{
memcpy(ParaBuffer,(u8*)LiftSystemaComParaAddr,520);
struct ElevatorFuncPara *temp_elevator_func_parameter = (struct ElevatorFuncPara*)&ParaBuffer[40];
temp_elevator_func_parameter->AccXBaseCount = elevator_func_parameter->AccXBaseCount;
temp_elevator_func_parameter->CloseLimitOffset = elevator_func_parameter->CloseLimitOffset;
temp_elevator_func_parameter->CloseStartTimeLimit = elevator_func_parameter->CloseStartTimeLimit;
temp_elevator_func_parameter->CloseStopTimeLimit = elevator_func_parameter->CloseStopTimeLimit;
temp_elevator_func_parameter->OpenLimitOffset = elevator_func_parameter->OpenLimitOffset;
temp_elevator_func_parameter->OpenStartTimeLimit = elevator_func_parameter->OpenStartTimeLimit;
temp_elevator_func_parameter->OpenStopTimeLimit = elevator_func_parameter->OpenStopTimeLimit;
temp_elevator_func_parameter->QuitCheckTime = elevator_func_parameter->QuitCheckTime;
STMFLASH_Write(LiftSystemaComParaAddr,(u32*)ParaBuffer,130);
}
STM32F4 Flash数据的保存和读取。
STM32 F4的存储和F1的存储稍稍有些区别。F4的最小存储单位是扇区,而F1的最小存储单位是页。(那么这样擦除的时候就存在区别,F1系的可以只擦除一页PAGES(最小1K),而F4需要擦除一个扇区SECTORS(最小16K),好处就是F1可以最大程度不影响本扇区非本页的数据,而F4则会影响本扇区数据)
STM32的读取比较简单,直接用指针指向对应的空间地址就可以取数据。最小可以写4个字节,即以字为存储单位。
u32 STMFLASH_ReadWord(u32 faddr)
{
return *(vu32*)faddr;
}
void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)
{
u32 i;
for(i=0;i
{
pBuffer
=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
ReadAddr+=4;//偏移4个字节.
}
}
STM32的写入稍微麻烦一点,需要先把扇区的数据擦除成0XFF,然后才可以写入数据。具体做法如地下:
1.禁止中断
2.flash解锁,禁止数据缓存
3.扇区擦除并检验
4.写入数据
5.开启数据缓存,flash上锁
7.开启中断
uint16_t STMFLASH_GetFlashSector(u32 addr)
{
if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
else if(addr
return FLASH_Sector_11;
}
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)
{
FLASH_Status status = FLASH_COMPLETE;
u32 addrx=0;
u32 endaddr=0;
if(WriteAddr
return; //非法地址
IntsStorage;
StoreDisableInts; //禁止中断
FLASH_Unlock(); //解锁
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存
addrx=WriteAddr; //写入的起始地址
endaddr=WriteAddr+NumToWrite*4; //写入的结束地址
if(addrx<0X1FFF0000) //只有主存储区,才需要执行擦除操作!!
{
while(addrx
{
if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
{
status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!!
if(status!=FLASH_COMPLETE)break; //发生错误了
}else addrx+=4;
}
}
if(status==FLASH_COMPLETE)
{
while(WriteAddr
{
if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据
{
break; //写入异常
}
WriteAddr+=4;
pBuffer++;
}
}
FLASH_DataCacheCmd(ENABLE); //FLASH擦除结束,开启数据缓存
FLASH_Lock();//上锁
RestoreInts; //开启中断
}
所以如果要修改扇区内的数据,则需要先将扇区内的数据取出来,然后修改对应的数据,最后再存入。
以修改一个结构体数据为例,先将数据使用memcpy函数cpy出来,然后使用结构体指向该数据,然后该结构体赋新值,最后再写入数据,这样就不会影响该扇区其他结构体的数据。
void UpdateSystemFuncParaData(struct ElevatorFuncPara *elevator_func_parameter)
{
memcpy(ParaBuffer,(u8*)LiftSystemaComParaAddr,520);
struct ElevatorFuncPara *temp_elevator_func_parameter = (struct ElevatorFuncPara*)&ParaBuffer[40];
temp_elevator_func_parameter->AccXBaseCount = elevator_func_parameter->AccXBaseCount;
temp_elevator_func_parameter->CloseLimitOffset = elevator_func_parameter->CloseLimitOffset;
temp_elevator_func_parameter->CloseStartTimeLimit = elevator_func_parameter->CloseStartTimeLimit;
temp_elevator_func_parameter->CloseStopTimeLimit = elevator_func_parameter->CloseStopTimeLimit;
temp_elevator_func_parameter->OpenLimitOffset = elevator_func_parameter->OpenLimitOffset;
temp_elevator_func_parameter->OpenStartTimeLimit = elevator_func_parameter->OpenStartTimeLimit;
temp_elevator_func_parameter->OpenStopTimeLimit = elevator_func_parameter->OpenStopTimeLimit;
temp_elevator_func_parameter->QuitCheckTime = elevator_func_parameter->QuitCheckTime;
STMFLASH_Write(LiftSystemaComParaAddr,(u32*)ParaBuffer,130);
}
举报