AVR看门狗及EEPROM
AVR单片机内部EEPROM应用方法

AVR 单片机内部EEPROM 应用方法
AVR 单片机内部集成了EEPROM,但是在GCC 写编写EEPROM 应用
程序的时候,经常会出现读写EEPROM 时程序出错,或重启等不正常现象。
在软件仿真时也许结果是正确的,但是在片上运行的时候就不正常。
困扰很
久,终于发现原因在于编译器,已经我们对EEPROM 操作说明的理解不正确
或不仔细。
操作EEPROM 对时序的要求较高。
更加Datasheet 里的写操作范例程序:while(EECR & (1EEAR = address; //设置地址和数据寄存器
EEDR = data;
EECR |= (1
EECR |= (1 以上代码在GCC 中的编译结果,发现EECR |= (1while(EECR & (1EEAR = address; //设置地址和数据寄存器
EEDR = data;
asm volatile(SBI 0x1C,2 \n\t);
asm volatile(SBI 0x1C,1 \n\t);。
AVR单片机看门狗的使用

开
验评 资 ¥ 150
开
USB转RS232开 4 数码 静态显 8 数码 态扫 4x4 键 ¥ 65 ¥ 40 显 ¥ 15 ¥ 40
/study/J0022.html
1
3
[2009/2/15 2:50:07]
单
开
验
创
单
MSP430单 AVR单 C8051F单 PIC单
开
TI
图讲 请 阅 骤 AVRmega16 册 “ 时 ” 节 P40 关内
导 HOLTEK单 STC单 ANALOG DEVICES IAR SYSTEM ICC Keil Protel IAR AVR 将 贴 项 JTAG main.c 讲 称为 AVRmega16 WatchDog 项
/************************************************** * * WatchDog 试验——AVRmega单 * * : __watchdog_reset();语 释 CPU * *时 2007 12 * * * * 编译环 IAR AVR V4.20A * 验 **************************************************/
单
开
验
创
[
绍] [
] [MSP430] [AVR] [51] [
][
][
载] [
购] [
论
][
][
][ 单
]
MSP430开
MSP430FET JTAG-I ¥ 120 MSP430FET JTAG-II ¥ 150 MSP430F135 验 -I ¥ 120 MSP430 验 -I ¥ 180 MSP430开 -II ¥ 200 MSP430 USB JTAG 资 EZ430 资 习 执 验 为 CPU 图 AVRmega16单 带
单片机-AVR-EEPROM的读写分析

1.单片机(AVR)EEPROM的读写分析由于AVR的EEPROM写周期比较长(一般为毫秒级),因此在编程使用过程中要特别注意.对于读EEPROM没什么好说的,读一个字节的数据要耗费4个时钟周期,可以忍受,写就比较麻烦了,虽然放在EEPROM的数据都不是频繁访问的;虽然可以用读-比较-写的机制降低EEPROM的写操作频度,但在写入过程中,过长的写入周期还是会造成一些问题,下面就分析一下几种方式的EEPROM写操作.1.1.循环查询式将地址和数据写入EEPROM相关的寄存器,置写标志后就循环不断查询写完成标志,直到写完成,退出循环,顺序执行其他程序.在置写入标志到写完成的这段时间,程序除了不断查询写完成标志和响应硬件中断之外什么也不干,这段时间就这么浪费了,如果是个实时性要求比较高的应用,浪费的就不仅是时间了,很可能在这段时间里I/O状态的变化不能得到及时的响应,如果一下子要进行多个字节的EEPROM的写入操作,那情况会更糟.针对这种情况,有种解决办法就是,这个写完成查询放在软件的死循环中(无操作系统的情况下,系统启动后都要进入一个死循环),每循环一次查询一次写完成标志,这样就不必一直等待写操作完成而可以干别的事情了,但是这样会带来两个问题.一是,如果死循环周期无法保证,则每一次的EEPROM写操作的完成标志查询也得不到保证,从而进行一次EEPROM写操作的周期也无法保证(最长延迟时间就是一个死循环周期的最长时间);二是,在执行一次EEPROM写入操作到写完成这段时间里死循环里其它的子程序不能进行EEPROM读写操作.第一个问题如果能保证最大循环周期在延迟允许范围内就不是问题了,否则就得采取下面讲到的方式二了;第二个问题的解决方法是每次EEPROM读写操作都要在其中加入对EEPROM写完成标志寄存器的判断,如果有数据正在写入,则等待或退出,但等待和退出又会造成等待延迟和写入操作不成功的问题,解决办法是先放入一个数据缓冲区,待上一次写入操作完成,再从缓冲区里拽出一个字节进行下一次写入周期,但这又会涉及到选择合适的缓冲区大小以及的问题,这个问题在下面中断式操作里继续讨论.1.2.定时查询式在写入EEPROM地址和数据寄存器置写标志后启动定时器,定时查询写完成标志,这种方法继承了方式1的大部分优缺点,唯一的进步就是能够确定写操作延迟时间为定时周期.1.3.中断式编写EEPROM写完成中断子程序,设置一个FIFO缓冲区,要写入的数据先放入这个FIFO,如果EEPROM操作空闲,则从FIFO中揪一字节数据出来写EEPROM,置完写完成标志就返回,然后去干别的事情,EEPROM写完成产生一个中断,在中断服务程序中再从FIFO中揪一个字节去写EEPROM,如此循环直到FIFO空,这种方式虽然能在第一时间完成一次写操作,但是还是有个和和方式1中提到一样的问题,怎么选择这个FIFO的大小.小了,待写入数据可能溢出丢失,大了,多大算大,1K够不够,10K够不够,硬件上有这么多RAM空间么,这就需要根据实际资源和系统需求来定了.如果EEPROM写操作频率很低,比一次EEPROM写操作间隔还要长得多,那么几个单位的FIFO就足够了;如果EEPROM写操作频率可能很高或一次大批量连续写入数据就要求很大的FIFO,达到能够保证数据不丢失,这就要根据批量数据大小和写频率来定了,另外还要考虑可用RAM空间的限制来找出最佳值,同时有FIFO溢出一定要制定相应的应对措施.最后注意两点:1.读写之前一定要检测是否已经有EEPROM写操作;在写完成之后一定要再读出写入的数据校验写入操作是否成功,不成功则EEPROM损坏,要做好应对措施.2.如果要保存一个16位的数据,一定要保证在这16位数据分成的两字节都成功写入了EEPROM再去读该数据,否则在刚写完一个字节就去读该数据,得到的数据显然不是你想要的,如果该数据是一重要参数,后果可想而知.。
avrEEPROM数据丢失问题原因与解决方案

avr EEPROM数据丢失问题原因与解决方案总结一下引起AVR内部EEPRO数据丢失的原因:1. 程序问题;2. 程序跑飞;3. EEPROM 相关寄存器因强磁场、高压静电等外部干扰出错所产生的写入动作;4. 系统有很大的感性负载,在断电的时候会产生一个反向高压,EEPRO有可能会自擦除。
…… (还有什么原因,欢迎大家继续列举,以便完善及想办法解决)针对问题1,程序问题不再该文讨论范围内。
针对问题2,程序跑飞,这个因该是引起EEPROI数据丢失的主要原因。
但是引起程序跑飞的原因却是多方面的第一. 电压不正常,工作不稳定,程序跑飞。
针对这个问题,可以开启内部BOD或者外加复位芯片解决,在低功耗场合,外部复位是有必要的,毕竟BOD功耗太高。
第二,晶体振荡受干扰,频率不稳定,程序跑飞。
针对这个问题,建议晶体使用全幅振荡,并且走线的时候尽量短,并且使用地线隔离。
第三系统受外界环境干扰,修改了PC等寄存器,程序跑飞。
针对这个干扰问题,这个引起程序跑飞的可能性应该不大,如果环境实在恶劣,那么就应该想到做电磁屏蔽,ESD保护等,如果还不行,那么只能建议换换别的单片机试试看了。
针对问题3,我们只能优化电路设置,尽量避免,比如加屏蔽罩,加ESD保护,力口TVS保护,电源加电容退耦等等。
针对问题4, 如果系统真的具有很大的感性负载,那么请注意加续流二极管、滤波电容等做保护,不要让这种反向高压产生,无论如何,这种因为感性负载突然断电自激产生的高压,不仅仅会对EEPRO有影响,而是对整个系统都存在威胁。
经过上面硬件上的一些处理,虽然EEPRO数据丢失的可能已经很小了,但是我们仍然不能保证EEPRO数据就不会丢失了。
这时EEPRO数据的可*性,那就得从软件上去考虑了,接着我们从软件的方面继续讨论。
我的做法是,数据分块,分区,校验,备份。
当然这里讲的处理方法,仅仅是提供一种想法,你可以做不同数据长度的分块,不同大小的分区,采用不同的地址映射方法,以及采用更多次的数据备份。
AVR的一点驯狗心得

AVR的一点驯狗心得新的AVR 系列(例如,ATMEGA168 等)使用增强功能的看门狗(Enhanced Watchdog Timer),与原来的看门狗相比较,除了有相同复位的功能以外,还增加了中断的功能设计时。
使用看门狗的中断功能,可以实现从Power Down 状态唤醒CPU;另外同时能使中断和复位功能,可以在系统发生错误时,先进入中断状态,保存关键数据到EEPROM,然后在进行系统复位。
AVR 新的看门狗与旧狗(例如,ATMEGA16 等)比较,增加了新的功能的同时脾气也有了不少改变。
设计时要摸清它的脾气,以防被狗咬。
下面说明以ATMEGA16 和ATMEGA168 作一个简单比较为例,简要地说明一下注意要点: 看门狗定时器控制寄存器– WDTCR: Atmega16: Atmega168: 1.A1tmega168 由于具有中断功能,所以WDTCR 增加了WDIF 和WDIE 两个额外的bit 的功能; 2.增加了WDP3,溢出周期可以有长达8 秒; 3.新的看门狗在初始化时,WDT 的值不再一定是0。
只要MCUSR 寄存器上的WDRF 置位,WDT 也将被强制置位。
这时,如果WDE 要清零,必须要WDRF 先清零。
4.在设计时即使不用WDT,它也可能在无意中被能使,例如在runaway 指针和调电情况下。
因此即使不用WDT,在初始代码中一定要检查复位标志,如果WDT 系统复位发生要采取处理步骤。
最近重新设计一个项目,由原先使用的ATMEGA16 更新到ATMEGA168。
把原代码转换后,测试结果异常。
经过一天多的测试,才发现是新的看门狗惹的祸。
以前用ATMEGA16,在初始化后才开始喂狗,可是新的AVR 系列(例如ATMEGA168 等),系统复位发生时(除上电复位外) ,WDT可能继续运行,并使用最小溢出周期(大约15mS) ,造成了系统不断复位。
根据datasheet,在程序开始时的关狗后一切就恢复正常了: #include #include uint8_t mcusr_mirror; void get_mcusr(void) __attribute__((naked))。
AVR单片机看门狗实验报告2013v1(有不同)

void watchdog_off(void)
{ /* Write logical one to WDTOE and WDE
这里严格要求这样的顺序*/
WDTCR = (1<<WDTOE) | (1<<WDE); /* Turn off WDT 这里严格要求这样的顺序*/
WDTCR = 0x00;
}
void Delay(void) { unsigned char i,j; for(i=200;i>0;i--)
{ for(j=100;j>0;j--); WDR(); //这里喂狗不然超过时间了
BIT 2、1、0 这三位设置看门狗溢出的间隔,在设置好的时间内不喂狗,就重启。
二、 具体例子(基于 ICCAVR7.22)
A、 打开和配置看门狗为最大时间间隔 2.2s void watchdog_on(void) { WDTCR |=(1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); }
{ } }
4.2 加入看门狗后
//ICC-AVR application builder : 2013-9-23 9:24:33 // Target : M16 // Crystal: 4.0000Mhz
#include <iom16v.h> #include <macros.h>
void port_init(void) { PORTD = 0x00; DDRD = 0xff; }
AVR单片机 看门狗范例 GCCAVR WDR 复位检测和控制看门狗

AVR单片机看门狗范例GCCAVR WDR 复位检测和控制看门狗内容来源:OURAVR发布时间:[2010-10-28]查看次数:805/*************************************************** AVR 复位检测和控制看门狗的范例******* ******* 作者:HJJourAVR ******* 编译器:WINAVR20050214 ******* ******* 2005.9.28 **************************************************//*本程序简单的示范了AVRATMEGA16的复位检测和控制看门狗系统控制和复位复位来源的检测JTAG复位指示看门狗复位指示BOD复位指示RESET引脚复位指示上电复位指示看门狗的控制出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器。
熔丝位设置1 使能BOD功能BODEN=02 选择BOD电平BODLEVEL=1 2.7V(VCC=3V) (可选)BODLEVEL=0 4.0V(VCC=5V) (可选)*/#include <avr/io.h>#include <avr/delay.h>//时钟定为内部RC 1MHz,F_CPU=1000000 也可以采用其他时钟#include <avr/wdt.h>/*wdt.h里面看门狗溢出时间常量定义#define WDTO_15MS 0#define WDTO_30MS 1#define WDTO_60MS 2#define WDTO_120MS 3#define WDTO_250MS 4#define WDTO_500MS 5#define WDTO_1S 6#define WDTO_2S 7下面的4S/8S定义只能用于 ATtiny2313, ATmega48, ATmega88 and the ATmega168.#define WDTO_4S 8#define WDTO_8S 9看门狗操作函数wdt_disable()关闭看门狗wdt_enable(timeout)使能看门狗及溢出时间设定wdt_reset()复位看门狗(喂狗)*///管脚定义#define WDT_EN 7 //PA7 看门狗的喂狗控制引脚// 高电平,不喂狗// 低电平,喂狗#define LED_JT 4 //PA4 JTAG复位指示#define LED_WD 3 //PA3 看门狗复位指示#define LED_BO 2 //PA2 BOD复位指示#define LED_EXT 1 //PA1 RESET引脚复位指示#define LED_PO 0 //PA0 上电复位指示//以上信号皆为低电平有效int main(void){unsigned char CPU_STATUS;unsigned char i;//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻PORTB=0xFF;//不用的管脚使能内部上拉电阻。
AVR复位

当然,在AVR的RST脚也接一个0.1uF的电容到GND,这电容的作用是很重要的。因为一般情况单片机受到干扰而复位基本是由于 RST受到干扰而 复位的。加上这个电容后有一定的作用,但也不是百分百的可以解决问题。所以前向的电源的处理很重要,前面的没处理好,5V端这边怎么折腾也是没什么好的效果。
当然,如果在交流侧有条件的话, 建议也加上EMI滤波电路。
我基本上按ATMEL提供的EMC注意手册里的说明来处理电源。现在把一个12V的直流电机直接接在正常工作的 ATTINY24 的系统里,然后不断的通断工作,相信这个干扰是很大的,但系统一直稳定工作,没有任何的死机复位现象。
PCB方面也是需要下工夫的,当然这个需要积累,建议多看看抗干扰方面的书籍和 PCB布线的书,收获是很大的。
随便说了一堆,可能还有很多片面的地方 ,希望对大家有所帮助。
使用AVR 芯片时, 很多人在实际使用的时候很容易出现工作过程中的复位,基本上是由于传导干扰造成的,而辐射干扰倒是可以通过PCB设计和铁壳屏蔽来解决。
而传导辐射就得需要在电源上下工夫了。
在5V直流电源端要做好滤波和去耦,在靠近AVR的VCC和GND的地方要加上0.1uF的独石电容或高频电容,可以很好的滤除从电源串入的高频脉冲干扰(这类的高频脉冲干扰基本上由同线路的电磁器件产生的,如电机、继电器,这类的器件多数情况下是和单片机同一路直流电源的,如12V、24V直流,而单片机的5V电源基本上是12V、24V电源端取的,然后进行稳压处理)。
掉电复位:就是在单片机运行过程中电压突然跌落,这个时候单片机会出现很多不确定的现象,所以在这个时候需要将单片机复位,让它处于一个确定的状态。这就是BOD功能,一个非常实用的功能,AVR单片机带有这个功能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#pragma data:data
内部EEPROM使用实例
�
定义RAM中的变量
�
SystemInfo sysdata={“GSM eHOME System”, “Ver 1.0”, “05/08/13 ”}; SysSetupType SetupData; SmsFileType SmsFile; AlamRecType AlamRec; uint8 SuperPassWord[16]; uint8 InputMenuInfo[8][20; uint8 OutputMenuInfo[8][20];
AVR 内置EEPROM
� �
在ICC中, eeprom.h头文件中预定义了内置 EEPROM读写宏: EEPROM_READ(int location, object)
�
�
这个宏调用了EEPROMReadBytes 函数从EEPROM 指定位置读取数据 送给数据对象 "object"可以是任意程序变量包括结构和数组例如
� �
在同一个指令内对WDTOE 和WDE 写"1“,即使WDE 已经为"1“ 在紧接的4 个时钟周期之内对WDE 写"0”
AVR 看门狗
AVR 看门狗
void WDT_off(void) { /* WDT 复位*/ _WDR(); /* 置位 WDTOE 和 WDE*/ WDTCR |= (1<<WDTOE) | (1<<WDE); /* 关闭WDT */ WDTCR = 0x00; }
AVR 内置EEPROM
� �
ATmega16 内置512字节的EEPROM 与EEPROM相关的寄存器
� � �
EEPROM 地址寄存器- EEARH和EEARL EEPROM 数据寄存器 - EEDR EEPROM 控制寄存器- EECR
AVR 内置EEPROM
�
EEPROM 地址寄存器- EEARH和EEARL
AVR 看门狗
AVR 看门狗
�
与看门狗相关的寄存器
�
WDTCR
�
WDTOE: 看门狗修改使能
�
清零WDE 时必须置位WDTOE,否则不能禁止看 门狗。一旦置位,硬件将在紧接的4 个时钟周期 之后将其清零。
AVR 看门狗
�
WDE: 使能看门狗
�
�
WDE为 “1 “ 时,看门狗使能,否则看门狗将被禁止。只有在 WDTOE为 ”1“ 时 WDE 才能清零。 以下为关闭看门狗的步骤:
�
�
指定了512字节的EEPROM空间。EEPROM地 址是线性的,从0 到511。 EEAR 的初始值没有定义。在访问 EEPROM 之前必须为其赋予正确的数据。
AVR 内置EEPROM
�
EEPROM 数据寄存器 - EEDR
�
�
对于EEPROM 写操作, EEDR 是需要写到 EEAR 单元的数据; 对于读操作, EEDR 是从地址EEAR 读取的 数据。
ICC中将变量分配至 EEPROM中
�
�
将变量分配到 EEPROM区域,可以使用编 译附注#pragma data:eeprom 将产生扩展名为 .eep 的EEPROM初始化 文件。
内部EEPROM使用实例
定义变量到EEPROM #pragma data:eeprom SystemInfo SysData; SysSetupType SetupEepData; SmsFileType SmsEepFile[10]; AlamRecType AlamEepRec[20]; uint8 SuperPassWordEep[16]; uint8 InputMenuInfoEep[8][20]; uint8 OutputMenuInfoEep[8][20]; uint8 SystemInit;
内部EEPROM使用实例
�
写入数据
�
EEPROM_WRITE((uint16)&SetupEepData,S etupData); EEPROM_READ((uint16)&SetupEepData,Se tupData);
�
读出数据
�
AVR 看门狗
�
பைடு நூலகம்
在ICC中,macros.h头文件中预定义了复位看门狗定时 器的宏
�
WDR()
//Watchdog initialize // prescale: 2048K void watchdog_init(void) { WDR(); //this prevents a timout on enabling WDTCR = 0x0F; //WATCHDOG ENABLED - dont forget to issue WDRs }
AVR 内置EEPROM
�
EEPROM 控制寄存器- EECR
�
EERE: EEPROM 读使能
�
� �
� �
当 EEPROM地址设置好之后,需置位 EERE以便将数据读入 EEAR 。 EEPROM 数据的读取只需要一条指令,且无需等待 。 读取 EEPROM后 CPU 要停止 4 个时钟周期才可以执行下一条指 令。 用户在读取 EEPROM 时应该检测 EEWE。 如果一个写操作正在进行,就无法读取 EEPROM,也无法改变 寄存器 EEAR。
第十二章 AVR看门狗及EEPROM
2007、06、26
AVR 看门狗
�
引入看门狗的意义
� �
防止程序跑飞 增强系统抗干扰能力
AVR 看门狗
AVR 看门狗
�
�
� �
�
看门狗使用一个独立的定时器,时钟源为内置 1Mhz独立振荡器 当看门狗定时器定时溢出时,将产生 1CLK 宽度 的复位脉冲 定时间隔由看门狗预分频器调节 程序执行时,定期复位看门狗定时器,以保证 看门狗不产生复位脉冲 程序跑飞时,由于在定时间隔内没有复位看门 狗定时器的操作,当定时溢出时,系统复位。
ICC中将变量分配至 EEPROM中
� � � � � � �
#pragma data:eeprom int foo = 0x1234; char table[] = { 0, 1, 2, 3, 4, 5 }; #pragma data:data ... int i; EEPROM_READ((int)&foo, i); // i 等于 0x1234
AVR 内置EEPROM
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) { /* 等待上一次写操作结束 */ while(EECR & (1<<EEWE)); /* 设置地址和数据寄存器 */ EEAR = uiAddress; EEDR = ucData; /* 置位 EEMWE */ EECR |= (1<<EEMWE); /* 置位 EEWE 以启动写操作 */ EECR |= (1<<EEWE); }
�
ICC读写EEPROM内置函数原型
unsigned char EEPROMread( int location) { EEAR = location; EECR |= 0x01; strobe return (EEDR); } // Set READ // Return byte
ICC读写EEPROM内置函数原型
� �
int i; EEPROM_Read(0x1, i); // 读 2 个字节给 i
�
EEPROM_WRITE(int location, object)
�
�
这个宏调用了EEPROMWriteBytes 函数将数据对象写入到EEPROM 的 指定位置 "object"可以是任意程序变量包括结构和数组例如
AVR 内置EEPROM
�
注意:
� �
� � � �
如果在步骤5 和6 之间发生了中断,写操作将失败。 因为此时EEPROM 写使能操作将超时。 如果一个操作EEPROM的中断打断了另一个 EEPROM操作,EEAR 或EEDR寄存器可能被修改, 引起EEPROM 操作失败。 建议此时关闭全局中断标志I。 经过写访问时间之后,EEWE 硬件清零。 用户可以凭借这一位判断写时序是否已经完成。 EEWE 置位后, CPU 要停止两个时钟周期才会运行 下一条指令。
AVR 内置EEPROM
unsigned char EEPROM_read(unsigned int uiAddress) { /* 等待上一次写操作结束 */ while(EECR & (1<<EEWE)); /* 设置地址寄存器*/ EEAR = uiAddress; /* 设置EERE 以启动读操作*/ EECR |= (1<<EERE); /* 自数据寄存器返回数据 */ return EEDR; }
AVR 内置EEPROM
�
EEPROM 控制寄存器- EECR
�
EERIE: 使能EEPROM 准备好中断
�
当EEWE 清零时EEPROM 准备好中断即可发 生。
AVR 内置EEPROM
�
EEPROM 控制寄存器- EECR
�
EEMWE: EEPROM 主机写使能
� �
� �
EEMWE决定了EEWE置位是否可以启动EEPROM写 操作。 当EEMWE为“1”时,在4个时钟周期内置位EEWE 将 把数据写入EEPROM 的指定地址; 若EEMWE 为“0“,则操作EEWE 不起作用。 EEMWE 置位后4 个周期,硬件对其清零。
AVR 内置EEPROM
�