电子说
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
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !