STM32F4フラッシュデータの保存と読み取り。

STM32F4フラッシュデータの保存と読み取り。

  STM32 F4のストレージは、F1のストレージとは少し異なります。F4の最小ストレージユニットはセクターであり、F1の最小ストレージユニットはページです。(この方法で消去する場合は違いがあります。F1はPAGESのページ(最小1K)しか消去できませんが、F4はセクターセクター(最小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<NumToRead;i++)
	{
    
    
		pBuffer[i]=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
		ReadAddr+=4;//偏移4个字节.	
	}
}

  STM32の書き込みは少し面倒です。データを書き込む前に、セクターのデータを0XFF消去する必要があります。具体的な方法は次のとおりです
。1。割り込みを禁止する
2.フラッシュロック解除、データキャッシュを禁止する
3.セクターの消去とチェック
4.データの書き込み
5.データキャッシュをオンにする、フラッシュロック
7.割り込みをオンにする


uint16_t STMFLASH_GetFlashSector(u32 addr)
{
    
    
	if(addr<ADDR_FLASH_SECTOR_1)return FLASH_Sector_0;
	else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_Sector_1;
	else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_Sector_2;
	else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_Sector_3;
	else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_Sector_4;
	else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_Sector_5;
	else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_Sector_6;
	else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_Sector_7;
	else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_Sector_8;
	else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;
	else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10; 
	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<STM32_FLASH_BASE||WriteAddr%4)
    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<endaddr)		//扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
        {
    
    
            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<endaddr)//写数据
        {
    
    
            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);
}

おすすめ

転載: blog.csdn.net/qq_34430371/article/details/107093288