历史上的今天
返回首页

历史上的今天

今天是:2025年04月01日(星期二)

正在发生

2019年04月01日 | STM32 Flash 均衡保存算法

2019-04-01 来源:eefocus

在实际应用中,经常需要在程序运行过程中保存或读取一些数据,这些数据在工作中经常会变化,而且掉电后也不能丢失,所以需要及时地进行存储,存储这些数据常用的存储器是 EEPROM。


STM32 虽然本身不带 EEPROM,但是它支持自编程技术,可以利用内部 FLASH 来模拟 EEPROM,这样不仅简化了设计,而且降低了成本。


FLASH 的擦写次数是有限的,一般是 10W 次, FLASH 单个存储单元bit只能从1变为0,而不能从0变成1。


想要变成1,只能 page 擦除,这里的 page 表示一个擦除单位,擦除过程就是把 page 所有的位都写1,这种硬件特性决定需要一种比较高效的写 flash 算法。


总不能一次更改数值时擦除整一大片 FLASH。


1、均值保存算法


处理方法是将 1024 字节按 16 字节大小分成 64 等份,按后面格式存储参数地址:


划分:0x10*n +0x00 +0x01  +0x02 ... +0x0E  +0x0F


内容:       flag  data1  data2 ... data14 data15  check_sum


check_sum=(flag+data1+data2+...+data15)&0xFF


flag 为 0xA5 表示当前 16 个字节为正在使用的记录,为其它值表示当前 16 字节已经丢弃。


这种保存方法是使用空间来换取擦写次数。


2、具体实现


1)定义 FLASH 页大小,储存数据大小:


#define FLASH_PAGE      1024

#define FLASH_DATAPACK  16  

2)定义一个储存结构体     


typedef struct {

  u32 Addr;            // 地址为 flash 一页的首地址

  u8  Read;            // 读地址的计数

  u8  Write;           // 写地址的计数

  u8  ReadBuff[FLASH_DATAPACK];  // 读取缓存区

  u8  WriteBuff[FLASH_DATAPACK];  // 写入缓存区

} EEPROMTypeDef;

// FLASH 写函数

void FlashWrite( EEPROMTypeDef *Flash_16 )

{

  u8 Flag;

  

  while_1:

  

  // 获取标志位

  Flag = *(vu8*)(Flash_16->Addr + (Flash_16->Write) * FLASH_DATAPACK);

  

  if(Flash_16->Write < 64 && Flag == 0xff)     // 如果地址在一页内且内容空白

  

  {

    HT_Flash_ByteWrite(Flash_16->WriteBuff, Flash_16->Addr + (Flash_16->Write++) * FLASH_DATAPACK,        FLASH_DATAPACK);

  }

  else if ( Flash_16->Write < 64 && Flag != 0xff ) // 如果地址在一页内却有数据存储

  {

    Flash_16->Write++;

    

    goto while_1;

  }     

  else if(Flash_16->Write >= 64 ) // 如果地址不在一页内

  {

    Flash_16->Write = 63;

  }

}

 

// FLASH 读函数

void FlashRead(EEPROMTypeDef *Flash_16)

{

  u8 Flag;

  

  while_1:

 

  // 获取标志位

  Flag = *(vu8*)(Flash_16->Addr + (Flash_16->Read) * FLASH_DATAPACK); 

 

  if( Flash_16->Read < 64 && Flag == 0xA5 )  // 如果地址在一页之内且数据有效

  {

    HT_Flash_ByteRead(Flash_16->ReadBuff, Flash_16->Addr + (Flash_16->Read) * FLASH_DATAPACK, FLASH_DATAPACK);  

 

  HT_Flash_ByteWrite(00, Flash_16->Addr + (Flash_16->Read++) * FLASH_DATAPACK, 1);  // 标记数据无效

  }

  else if(Flash_16->Read < 64 && Flag != 0xA5) // 如果地址在一页之内但数据无效

 {    

   if(Flag != 0xff)

    {                   

      Flash_16->Read++;

      

      goto while_1;

    }

  }     

 

  else if(Flash_16->Read >= 64)  // 如果地址不在一页之内

  {

    Flash_16->Read = 0;

 

    Flash_16->Write = 0;

 

    HT_Flash_PageErase(Flash_16->Addr); // 页擦除

  }

}

 

推荐阅读

史海拾趣

ERNI公司的发展小趣事

进入21世纪,ERNI继续深耕连接器技术。他们成功研发出世界上第一个DIN连接器,并随后发展了各种电路板连接器和输入/输出连接器。其中,2mm连接器成为ERNI的明星产品之一。凭借其优越的性能和可靠的品质,ERNI的2mm连接器在国内军工领域得到广泛应用,并赢得了广大客户的信赖和好评。

Advanced Linear Devices公司的发展小趣事

进入20世纪60年代,ERNI开始关注连接器技术的发展。他们意识到,随着电子设备的日益复杂和多样化,对连接器技术的需求也将不断增长。因此,ERNI投入大量资源进行研发,终于在1967年成功开发出第一个背板连接器,这一创新技术迅速成为公司的核心产品,也为ERNI在连接器市场赢得了声誉。

GE公司的发展小趣事

进入20世纪60年代,ERNI开始关注连接器技术的发展。他们意识到,随着电子设备的日益复杂和多样化,对连接器技术的需求也将不断增长。因此,ERNI投入大量资源进行研发,终于在1967年成功开发出第一个背板连接器,这一创新技术迅速成为公司的核心产品,也为ERNI在连接器市场赢得了声誉。

FILTRAN公司的发展小趣事

1947年,瑞士工程师Ernst Rudolf Erni和他的妻子Elsa在瑞士那提空(Nänikon)共同创立了“ERNI & CO.”公司。他们的首个订单是为苏黎世克洛腾机场开发地雷探测器和机场导航灯。这个起点虽小,但为ERNI日后在电子行业的辉煌奠定了基础。随着订单的增多,公司逐渐扩大了生产规模,并开始涉足继电器、电气设备等领域。

Brand-Rex公司的发展小趣事

Brand-Rex的综合布线产品在国家重大项目上得到了广泛应用。例如,昌北国际机场作为中国干线机场,其总建筑面积达到96616平方米。该项目于2010年9月中标,2011年5月22日竣工并投入使用。整个系统均采用了Brand-Rex的CAT6PLUS全系列铜缆和光纤产品,充分展示了Brand-Rex在大型项目中的技术实力和产品可靠性。此外,Brand-Rex还参与了其他多个重要项目的布线工作,为国家基础设施的建设做出了积极贡献。

Dielectric Laboratories公司的发展小趣事

在电子元件市场竞争日益激烈的背景下,DLI意识到必须不断创新才能保持竞争优势。于是,公司开始研发多层陶瓷电容器(MLCC)技术。经过数年的努力,DLI成功推出了具有高性能、高可靠性特点的多层陶瓷电容器,广泛应用于军事、航空等领域。这一技术的突破不仅提升了DLI的市场地位,也为整个电子行业的发展做出了重要贡献。

问答坊 | AI 解惑

直流稳压电源 电子大赛培训资料

本帖最后由 jameswangsynnex 于 2015-3-3 20:00 编辑 …

查看全部问答>

基于proteus的喇叭的应用实例或单片机实现的音乐贺卡

单片机实现类似音乐贺卡的功能,自己选择一段音乐用单片机驱动喇叭播放出来,…

查看全部问答>

急求VHDL高手进来帮我看一看

没有语法错误,但找不到症结在哪,请帮忙看一下,感谢! QQ704443450。小女子在线等…

查看全部问答>

ClearCommError问题

COMSTAT ComStat ClearCommError(m_hCom,&dwErrorFlags,&ComStat); 这个函数用于清除硬件错误和获取状态(我是的重叠操作) 我WriteFile后,ReadFile前怎么这个结构的cboutbuf永远是0,为什么不是我写入的字节 单步调试N此不知为何?恭请高手解 ...…

查看全部问答>

png按钮的资源释放问题

开发环境:vc2005  arm   wince5.0 我用网上下的CCePngButtonST类做png按钮,想要实现同一个按钮上的png图片根据不同情况显示不同内容,比如播放器打开时显示一张图片,播放器关闭时显示另一张图片,结果点了n次后把内存都占 ...…

查看全部问答>

机顶盒界面开发咨询

请问各位大侠如何做比较酷的机顶盒界面(比如说立体按钮)? 用C或C++. 只能自己画吗? 有什么注意的地方? 谢谢了 …

查看全部问答>

dereferencing type-punned pointer will break strict-aliasing rules

static int print(char **out, int *varg) {         register int width, pad;         register int pc = 0;         register char *format = (char *)(*varg++);   &nb ...…

查看全部问答>

DS1302程序读写

DS1302程序读写;对初学者很有帮助的哟;对C语言老手也很有参 考价值!…

查看全部问答>

DSP代码运行报错,求高人指点

cmd文件内一段代码如下: _EVENT72 = EVENT72;_EVENT73 = EVENT73;_EVENT74 = EVENT74;_EVENT75 = EVENT75;_EVENT76 = EVENT76;_EVENT77 = EVENT77;_EVENT78 = EVENT78; CCS 4内,debug运行后报错:   absolute symbol \"_EVENT72\" being ...…

查看全部问答>