使用MCU Flash模拟EEPROM

电子说

1.2w人已加入

描述

 

1、概述

ME32x系列是内嵌ARM Cortex™ M0/M3核的32位微控制器。该系列控制器由敏矽微电子有限公司自主开发,并具有自主知识产权。敏矽微电子的微控制器包括有通用MCU和专用SOC系列,具有非常高的性价比,是MCU产品升级换代和国外产品替代的最佳选择。通用功能有高精度ADC,CAN接口,I2S音频接口,UART串口,SPI接口,I2C总线接口,看门狗定时器(WDT),通用计数器/定时器。特殊接口包括人机界面控制器(LCD驱动,电容触摸按键)和马达控制功能模块。

EEPROM作为比较廉价和方便数据存储器,被广泛使用并且习惯思维。而MCU Flash与EEPROM相比,除使用方法略有差异外,作为数据存储器,所起的效果是一样的。

2、MCU Flash与EEPROM使用比较

 

擦除

擦除时间

编程

编程时间

硬件接口

擦写寿命

MCU Flash

扇区为单位擦除,擦除后数据为0xFF

5ms

32位word 编程

7us

通过寄存器接口设置编程,读Flash通过指针直接读

10万次

EEPROM

没有单独擦除功能

-

Byte编程

-

I2C接口

100万次

3、使用MCU Flash 存储数据举例

以ME32S003系列为例,下面说明如何使用MCU Flash 存储小量的数据(注意,本例重点在探讨实现的一个思路,程序调试请用户自行解决)。

ME32S003系列有32K Flash,我们拿出1K, 即两个扇区来存储数据,在这里约定一个数据存储单元为64 Bytes(包括标志)。

两个扇区有16个存储单元,换句话说,可以存储10万x 16 =160 次数据,远远超过EEPROM的寿命。

所有需要存储数据放在一个数据结构中,方便存储和提取数据:

#defineDATA_AREA_ADDRESS 62*512 //数据扇区起始地址
#defineDATA_AREA_SIZE 2*512 //两个扇区大小
#defineDATA_UINT_SIZE 64 //每一个存储单元大小,一定要整除扇区大小(512)
#defineDATA_UINT_FLAG 0x5555AAAA
typedef struct {
uint32_t flag;
uint32_t data1;
…
} data_uint_type;
voidflash_erase(uint32_t startaddr, uint32_t size)
{
uint32_t endaddr;
endaddr=startaddr+size;
     //erase sector
     while(startaddrADDR = startaddr; // setup addr
              FMC->CMD = 0x04; //Triggerprogramming
              while ((FMC->CMD  0x100)!=0);
              startaddr+=512;
     }
return;  
}
uint8_t flash_word_program(uint32_taddr, uint32_t worddata) //返回一个非0的数据当错误发生时
{
     //program word
              FMC->ADDR = addr; // set upaddr     
              FMC->DATA =worddata;
              FMC->CMD = 0x02; //Triggerprogramming
              while ((FMC->CMD  0x100)!=0);
              if (*(uint32_t *)addr== worddata)
      return 0;
else
      return 1;
}
data_uint_type* data_area_init(void)//返回一个指向数据单元的指针,空指针表示没有数据
{
data_uint_type* ptr;
ptr=get_last_data_uint_ptr();
if (((uint32_t) ptr==DATA_AREA_ADDRESS)  (ptr->flag!==DATA_UINT_FLAG))
{
flash_erase(DATA_AREA_ADDRESS,DATA_AREA_SIZE);
ptr= null;
}
}
data_uint_type* get_last_data_uint_ptr(void)//返回一个指向数据单元的指针
{
uint32_tstartuintaddr,enduintaddr,temp;
startuintaddr= DATA_AREA_ADDRESS/DATA_UINT_SIZE;
enduintaddr= startuintaddr+DATA_AREA_SIZE/ DATA_UINT_SIZE-1;
while(startuintaddr!=enduintaddr)
{
              temp= (startuintaddr+ enduintaddr)>1;
              if ((data_uint_type*)(temp* DATA_UINT_SIZE)->flag==DATA_UINT_FLAG)
                       startuintaddr= temp;          
else
                enduintaddr= temp
}
startuintaddr =startuintaddr * DATA_UINT_SIZE;
if (((data_uint_type*)startuintaddr)->flag!=DATA_UINT_FLAG)
return (data_uint_type*) 0;
else
                {
                        If (startuintaddr< (DATA_AREA_ADDRESS+DATA_AREA_SIZE))
                                 {
                                          If  (((data_uint_type*)(startuintaddr+ DATA_UINT_SIZE)->flag==DATA_UINT_FLAG)
                                          return(data_uint_type*)(startuintaddr+ DATA_UINT_SIZE) ;
}else
return (data_uint_type*)(startuintaddr) ;
}
}
uint8_tstore_data_uint(data_uint_type* sur_data_ptr, data_uint_type* dst_data_ptr) //返回一个非0的数据当错误发生时
{
     uint32_t n,temp0,temp1,temp2,*dataptr;
     temp1= sizeof(data_uint_type) >>2;
if((temp1<<2)!= sizeof(data_uint_type))
     temp1++;
     temp2=(uint32_t) dst_data_ptr;
     dataptr=(uint32_t *) sur_data_ptr;
     //erase sector
     if ((DATA_AREA_ADDRESS==temp2)  (dst_data_ptr->flag==DATA_UINT_FLAG))
     {
              flash_erase(DATA_AREA_ADDRESS, DATA_AREA_SIZE);//erase whole data sectors
     }
     for (n=0;n

系统启动时,先调用data_area_init()函数,返回当前数据单元指针,你可以使用memory copy 复制数据到你的程序中。如果是空指针,你需要对你的数据赋予初值,并把它存储到数据区。

全局变量:

data_uint_typemydata;
data_uint_type * dataptr;
main(void)
{
…
dataptr=data_area_init();//初始化
if((uint32_t)dataptr==0) //空指针
{
//对mydata赋予初值
…
//存储数据到Flash 数据区
data_ptr =(data_uint_type *) DATA_AREA_ADDRESS;
store_data_uint( mydata,data_ptr);
}
…
//任何时候,调用store_data_uint()把mydata数据存储到Flash
data_ptr++;
if ((uint32_t)data_ptr==DATA_AREA_ADDRESS)
data_ptr =(data_uint_type *) DATA_AREA_ADDRESS;
store_data_uint( mydata,data_ptr);
…
//data_ptr永远指向当前Flash 数据
…
}

注意事项:

由于mydata的地址是编译器自动设定的,如果发生mydata地址不是word对齐地址,需要手动设置。总之,要确保mydata地址是word对齐的。

4、Revision History

来源:敏矽MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理

审核编辑 黄宇


;n++)>)>

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分