OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2571|回复: 0

STM32F215 内部FLASH读写无法保存数据

[复制链接]

22

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2016-5-17
在线时间
29 小时
发表于 2017-9-13 09:39:36 | 显示全部楼层 |阅读模式
[AGV{F5M188QY0QE@169)8J.png 请问 这个是STM32F215内部FLASH 如果用 F4例子写FLASH会无法保存里面的数据请问有其他方法吗

u32 STMFLASH_ReadWord(u32 faddr){
        return *(vu32*)faddr;
}

//获取某个地址所在的flash扇区
//addr:flash地址
//返回值:0~11,即addr所在的扇区
u8 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;
        else if(addr<ADDR_FLASH_SECTOR_12)return FLASH_SECTOR_11;
        else if(addr<ADDR_FLASH_SECTOR_13)return FLASH_SECTOR_12;
        else if(addr<ADDR_FLASH_SECTOR_14)return FLASH_SECTOR_13;
        else if(addr<ADDR_FLASH_SECTOR_15)return FLASH_SECTOR_14;
        else if(addr<ADDR_FLASH_SECTOR_16)return FLASH_SECTOR_15;
        else if(addr<ADDR_FLASH_SECTOR_17)return FLASH_SECTOR_16;
        else if(addr<ADDR_FLASH_SECTOR_18)return FLASH_SECTOR_17;
        else if(addr<ADDR_FLASH_SECTOR_19)return FLASH_SECTOR_18;
        else if(addr<ADDR_FLASH_SECTOR_20)return FLASH_SECTOR_19;
        else if(addr<ADDR_FLASH_SECTOR_21)return FLASH_SECTOR_20;
        else if(addr<ADDR_FLASH_SECTOR_22)return FLASH_SECTOR_21;
        else if(addr<ADDR_FLASH_SECTOR_23)return FLASH_SECTOR_22;  
        return FLASH_SECTOR_23;       
}

//从指定地址开始写入指定长度的数据
//特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数
//         写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以
//         写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里
//         没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.
//该函数对OTP区域也有效!可以用来写OTP区!
//OTP区域地址范围:0X1FFF7800~0X1FFF7A0F(注意:最后16字节,用于OTP数据块锁定,别乱写!!)
//WriteAddr:起始地址(此地址必须为4的倍数!!)
//pBuffer:数据指针
//NumToWrite:字(32位)数(就是要写入的32位数据的个数.)
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)       
{
        FLASH_EraseInitTypeDef FlashEraseInit;
        HAL_StatusTypeDef FlashStatus=HAL_OK;
        u32 SectorError=0;
        u32 addrx=0;
        u32 endaddr=0;       
        if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;        //非法地址

        HAL_FLASH_Unlock();             //解锁       
        addrx=WriteAddr;                                //写入的起始地址
        endaddr=WriteAddr+NumToWrite*4;        //写入的结束地址

        if(addrx<0X1FFF0000)
        {
                while(addrx<endaddr)                //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
                {
                         if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
                        {   
                                FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS;       //擦除类型,扇区擦除
                                FlashEraseInit.Sector=STMFLASH_GetFlashSector(addrx);   //要擦除的扇区
                                FlashEraseInit.NbSectors=1;                             //一次只擦除一个扇区
                                FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3;      //电压范围,VCC=2.7~3.6V之间!!
                                if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK)
                                {
                                        break;//发生错误了       
                                }
                                }else addrx+=4;
                                FLASH_WaitForLastOperation(FLASH_WAITETIME);                //等待上次操作完成
                }
        }
        FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME);            //等待上次操作完成
        if(FlashStatus==HAL_OK)
        {
                 while(WriteAddr<endaddr)//写数据
                 {
                        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,WriteAddr,*pBuffer)!=HAL_OK)//写入数据
                        {
                                break;        //写入异常
                        }
                        WriteAddr+=4;
                        pBuffer++;
                }  
        }
        HAL_FLASH_Lock();           //上锁
}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 01:10

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表