STM32
直播中

陆军航空兵

8年用户 793经验值
私信 关注
[问答]

如何利用stm32f407内部的flash去保存数据呢

如何利用STM32f407内部的flash去保存数据呢?

回帖(1)

孙巍

2021-12-15 14:47:14

#include "stm32f4xx.h"

//FLASH起始地址
#define STM32_FLASH_BASE 0x08000000     //STM32 FLASH的起始地址
#define FLASH_SAVE_ADDR  0x080A0000    //保存地址


//FLASH 扇区的起始地址
#define ADDR_FLASH_SECTOR_0     ((u32)0x08000000)     //扇区0起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_1     ((u32)0x08004000)     //扇区1起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_2     ((u32)0x08008000)     //扇区2起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_3     ((u32)0x0800C000)     //扇区3起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_4     ((u32)0x08010000)     //扇区4起始地址, 64 Kbytes  
#define ADDR_FLASH_SECTOR_5     ((u32)0x08020000)     //扇区5起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_6     ((u32)0x08040000)     //扇区6起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_7     ((u32)0x08060000)     //扇区7起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_8     ((u32)0x08080000)     //扇区8起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_9     ((u32)0x080A0000)     //扇区9起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_10    ((u32)0x080C0000)     //扇区10起始地址,128 Kbytes  
#define ADDR_FLASH_SECTOR_11    ((u32)0x080E0000)     //扇区11起始地址,128 Kbytes  



//读取指定地址的半字(16位数据)
//faddr:读地址
//返回值:对应数据.
u32 STMFLASH_ReadWord(u32 faddr)
{
    return *(vu32*)faddr;
}  
//获取某个地址所在的flash扇区
//addr:flash地址
//返回值:0~11,即addr所在的扇区
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;   
}
//从指定地址开始写入指定长度的数据
//特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数
//         写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以
//         写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里
//         没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.
//该函数对OTP区域也有效!可以用来写OTP区!
//OTP区域地址范围:0X1FFF7800~0X1FFF7A0F
//WriteAddr:起始地址(此地址必须为4的倍数!!)
//pBuffer:数据指针
//NumToWrite:字(32位)数(就是要写入的32位数据的个数.)
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)   
{
    FLASH_Status status = FLASH_COMPLETE;
    u32 addrx=0;
    u32 endaddr=0;   
    if(WriteAddr     FLASH_Unlock();     //解锁
    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();//上锁
}

//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToRead:字(4位)数
void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)      
{
    u32 i;
    for(i=0;i     {
        pBuffer=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
        ReadAddr+=4;//偏移4个字节.
    }
}


void FLASHEXT_ReadFlash( u8 *pbData, u32 dwDataLen )
{  
    u32  Len;
    u32  dwData;
    u32  i=0,j=0;

   
    Len=  dwDataLen/4+((dwDataLen%4)?1:0);

    STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)(pbData),Len);
  
    return;
}

void FLASHEXT_WriteFlash( u8 *pbData, u32 dwDataLen )
{
         
    u32     Len;
    u32     dStartTime;
    u8      pu8ReadData[60];
    u8      i=0;
    Len=  dwDataLen/4+((dwDataLen%4)?1:0);
   
    STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)(pu8ReadData),Len);

    for(i=0;i     {
       if(pbData!=pu8ReadData)
       {
           STMFLASH_Write(FLASH_SAVE_ADDR,(u32*)(pbData),Len);
           break;
       }
    }
   

    return ;
}
举报

更多回帖

×
20
完善资料,
赚取积分