AVR内部EEPROM数据丢失问题的原因与解决方案

发布者:快乐旅行最新更新时间:2012-08-16 来源: 51hei关键字:AVR  EEPROM  数据丢失 手机看文章 扫描二维码
随时随地手机看文章

总结一下引起 AVR 内部 EEPROM 数据丢失的原因:

    1. 程序问题;
    2. 程序跑飞;
    3. EEPROM相关寄存器因强磁场、高压静电等外部干扰出错所产生的写入动作;
    4. 系统有很大的感性负载,在断电的时候会产生一个反向高压,EEPROM有可能会自擦除。
      ……(还有什么原因,欢迎大家继续列举,以便完善及想办法解决)

    针对问题1,程序问题不再该文讨论范围内。

    针对问题2,程序跑飞,这个因该是引起 EEPROM 数据丢失的主要原因。但是引起程序跑飞的原因却是多方面的。
    
    第一. 电压不正常,工作不稳定,程序跑飞。针对这个问题,可以开启内部BOD、或者外加复位芯片解决,在低功耗场合,外部复位是有必

要的,毕竟BOD功耗太高。

    第二,晶体振荡受干扰,频率不稳定,程序跑飞。针对这个问题,建议晶体使用全幅振荡,并且走线的时候尽量短,并且使用地线隔离。

    第三系统受外界环境干扰,修改了PC等寄存器,程序跑飞。针对这个干扰问题,这个引起程序跑飞的可能性应该不大,如果环境实在恶劣

,那么就应该想到做电磁屏蔽,ESD保护等,如果还不行,那么只能建议换换别的单片机试试看了。

    针对问题3,我们只能优化电路设置,尽量避免,比如加屏蔽罩,加ESD保护,加TVS保护,电源加电容退耦等等。

    针对问题4, 如果系统真的具有很大的感性负载,那么请注意加续流二极管、滤波电容等做保护,不要让这种反向高压产生,无论如何,这

种因为感性负载突然断电自激产生的高压,不仅仅会对EEPROM有影响,而是对整个系统都存在威胁。

经过上面硬件上的一些处理,虽然EEPROM数据丢

失的可能已经很小了,但是我们仍然不能保证EEPROM数据就不会丢失了。这时 EEPROM 数据的可*性,那就得从软件上去考虑了,接着我们从

软件的方面继续讨论。

    我的做法是,数据分块,分区,校验,备份。当然这里讲的处理方法,仅仅是提供一种想法,你可以做不同数据长度的分块,不同大小的 分区,采用不同的地址映射方法,以及采用更多次的数据备份。下面以 Mega168 为例继续讨论。 [page]

 1. Mega168 EEPROM 512字节,把EEPROM分为两个区,每个区256个字节,然后以8个字节为一个段,那么每个区就有32段。 
    数据区:0x000 - 0x0FF  
    0段:0x000 - 0x007 
    1段:0x008 - 0x00F 
       …… 
    31段:0x0F8 - 0x0FF 

    备份区:0x100-0x1FF

    每个段8个字节,其中前6个字节为有效数据,后2个字节为CRC16校验,数据格式下图所示:

 点击浏览下一页
 

 2. EEPROM读写操作
    EEPROM的操作以段为单位,
    段写入函数:写数据到数据区时,先计算数据CRC16校验,然后同时把数据写入到数据区和备份区;
    段读取函数:读取数据时,同时读取数据区以及备份区,如果数据区校验有误,备份区数据校验正确,就用备份区数据恢复数据区数据;  

  如果备份区数据有误,数据区数据正确,那么数据写入备份区重新备份;如果数据区备份区数据都有误,那么返回读取失败。

3. 数据区与备份区的对应关系
    数据读写操作以段进行,内部的数据区与备份区怎么映射呢?为了防治数据与备份同时被意外修改,那么数据与备份地址空间相隔不能太

近,并且数据与备份的地址,应该尽量不同。假设数据地址为 Data_Addr,备份地址为 Bakup_Addr,我使用下面的函数映射地址:
                 Bakup_Addr = ( Data_Addr + 0x100 ) ^ 0x03F 
    加0x100是把地址定义到备份区, 与0x03F异或,是把低6bits取反,这样处理,数据与备份的地址空间较远,并且地址有7bits的不同。
    例如,第 3 段 的地址: 0x018 - 0x01F, 
          对应的备份区为:0x127 - 0x120 
          如下图所示:  
 点击浏览下一页
 

 

4. 读写函数加入写保护判断,在读写EEPROM前关闭写保护,读写完毕后,立即开启写保护,这样可以有效防止程序跑飞造成的EEPROM意外修改



5. 第0块建议禁止使用。

关键字:AVR  EEPROM  数据丢失 引用地址:AVR内部EEPROM数据丢失问题的原因与解决方案

上一篇:基于ATmega128编码器控制步进电机的平衡系统
下一篇:一个简单的AVR门禁系统代码

推荐阅读最新更新时间:2024-03-16 13:05

关于IIC EEPROM页写丢数据问题
无论从那个地址连续写,不能超过(跨过)一整页。 先明白页写的道理。 AT24CXX系列的EEPROM为了提高写效率,提供了页写功能,内部有个一页大小的写缓冲RAM,地址范围当然就是从00到一页大小,发生写操作时,开始送入的地址对应的页被选中,并将其内容映像到缓冲RAM,数据从低端地址对应的缓冲RAM地址开始修改,超过这个地址范围就回到00,写完后,就会把开始确定的EEPROM页擦除,再把一整页RAM数据写入。所有写数据都发生在开始写地址时确定的页上。 如页容量为128,一页都是从00开始按128字节分成一个个的页,0页就是0~7F,1页就是80~FF,类推,边界就是128字节的整数倍地址。页RAM的地址范围为7位00~7F,写入时
[单片机]
AVR单片机与串行时钟器件DS3231的接口设计
1 引言 由单片机构成的测控系统或智能显示屏经常需要用到实时日历或时钟信号。为节省CPU资源,本文介绍了串行时钟器件DS3231的应用及其与AVR单片机ATmega8的接口,该系统具有抗干扰能力强,计时准确且不随季节变化产生误差的特点。 2 DS3231的结构及工作原理 DS3231是低成本、高精度I2C实时时钟(RTC)器件,具有集成的温度补偿晶体振荡器(TCXO)。该器件包含电池输入端,断开主电源时仍可保持精确计时。集成的晶体振荡器可提高器件的长期精确度。DS3231的寄存器能保存秒、分、时、星期、日期、月、年和闹钟设置等信息。少于31天的月份,可自动调整月末日期,包括闰年补偿。时钟的工作格式为24小时或带AM/PM指示
[应用]
AVR的锂电池智能充电器的设计与实现
1 引言 锂电池闲其比能量高、自放电小等优点,成为便携式电子设备的理想电源。近年来,随着笔记本电脑、PDA,无绳电话等大功耗大容量便携式电子产品的普及,其对电源系统的要求也日益提高。为此,研发性能稳定、安全可靠、高效经济的锂电池充电器显得尤为重要。 本文在综合考虑电池安全充电的成本、设计散率及重要性的基础上,设计了一种基于ATtiny261单片机PWM控制的单片开关电源式锂电池充电器,有效地克服了一般充电器过充电、充电不足、效率低的缺点,实现了对锂电池组的智能充电,达到了预期效果。该方案设计灵活,可满足多种型号的锂电池充电需求,且ATtiny261集成化的闪存使其便于软件调试与升级。 2 锂电池充电特性
[单片机]
<font color='red'>AVR</font>的锂电池智能充电器的设计与实现
24C02(EEPROM)记忆开机次数程序
24C02记忆开机次数,开机次数存放地址为00H,做此实验时,先用地址清0程序将00H清0,再去做记忆开机次数实验!!! 计数地址清0程序如下: ;///////////////////////////////////////////////////// ;将AT24C02(EEPROM)的00H单元的地址清0 ;AT24C02存储开机次数(准备程序) ;//////////////////////////////////////////////////// WP BIT P1.0 SCL BIT P1.1 SDA BIT P1.2 WRDA EQU 41H ORG 0000H SJMP MAIN ORG 0030H MAIN
[单片机]
24C02(<font color='red'>EEPROM</font>)记忆开机次数程序
AT240C02中EEPROM保存数据
/*********************** 程序功能: 利用定时器产生一个0~99秒变化的秒表,并且显示在数码管上, 每过一秒将这个变化的数写入板上AT24C02内部。当关闭电源, 并再次打开电源时,单片机先从AT24C02中将原来写入的数读取出来, 接着此数继续变化并显示在数码管上。 ************************/ /************************ CODE: ************************/ #include reg52.h #define uint unsigned int #define uchar unsigned char #define AT
[单片机]
AVR(ATMEGA128\16)SPI通信
以下是主机部份 #include iom128v.h #include macros.h #define uchar unsigned char #define uint unsigned int #include delay.h #include lcd.h void port_init(void); //SPI initialize // clock rate: 1843199hz void spi_init(void) { SPCR = 0x74; //setup SPI SPSR = 0x00; //setup SPI DDRB=0X07; PORTB|=0X08; } //call this r
[单片机]
<font color='red'>AVR</font>(ATMEGA128\16)SPI通信
AVR发送一个字符
#include avr/io.h #include avr/interrupt.h int k; void init(void) { UCSR0B=0b00011000; UCSR0C=0X06; UBRR0L=51; UBRR0H=0; TIMSK=0x01; TCCR0=0X05; TCNT0=0; } int main(void) { init(); DDRA=0XFF; PORTA=0XFF; sei(); while(1); } ISR(TIMER0_OVF_vect) { k++; if(k 200) { TIMSK=0x00; PORTA=~PORT
[单片机]
AVR开发 Arduino方法(一) 端口子系统
  Arduino UNO R3的主处理器ATMega328P上有3个8位的输入/输出端口,分别是PB,PC和PD。Arduino IDE提供的Blink示例可以帮助我们了解端口的数字输出功能: 1 // Blink.ino 2 int led = 13; 3 4 void setup() { 5 pinMode(led, OUTPUT); 6 } 7 8 void loop() { 9 digitalWrite(led, HIGH); 10 delay(1000); 11 digitalWrite(led, LOW); 12 delay(1000); 13 }   这个示例使Arduino开发
[单片机]
<font color='red'>AVR</font>开发 Arduino方法(一) 端口子系统
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved