ATmega128包含4K字节的EEPROM。它是作为一个独立的数据空间而存在的,可以按字节读写。EEPROM的寿命至少为 100,000 次(擦除)。EEPROM的访问由地址寄存器,数据寄存器和控制寄存器决定。
1.EEPROM 数据存储器
ATmega128包含4K字节的EEPROM。它是作为一个独立的数据空间而存在的,可以按字 节读写。EEPROM 的寿命至少为100,000 次(擦除)。EEPROM 的访问由地址寄存器, 数据寄存器和控制寄存器决定。具体的SPI 和JTAG 下载EEPROM 数据请分别参见芯片手册中P267“ 存储器编程” 。
2.EEPROM 读/ 写访问
EEPROM 的访问寄存器位于I/O 空间。EEPROM 的写访问时间由Table 2 给出。
自定时功能可以让用户监测何时开始写下一字 节。如果用户要操作EEPROM,应当注意如下问题:在电源滤波时间常数比较大的电路 中,上电/ 下电时VCC 上升/ 下降速度会比较慢。此时CPU 将工作于低于晶振所要求的 电源电压。请参照 P 22 “ 防止EEPROM 数据丢失” 以防止如何在此时出现EEPROM 的 数据丢失问题。
为了防止无意识的EEPROM 写操作,需要执行一个特定的写时序。具体参看EEPROM 控制寄存器的内容。
当执行EEPROM 读操作时, CPU 会停止工作4 个周期,然后再执行后续指令;当执行 EEPROM 写操作时, CPU 会停止工作2 个周期,然后再执行后续指令。
3.EEPROM 地址寄存器-EEARH 和EEARL
• Bits 15..12 – Res: 保留
保留位,读操作返回值为零。在写数据时要写入 0 以保证与未来产品的兼容。
• Bits 11..0 – EEAR11..0: EEPROM地址
EEARH和EEARL指定了4K字节的EEPROM空间。EEPROM的地址是线性的,从0到4096。EEAR 的初始值没有定义。在访问 EEPROM 之前必须为其赋予正确的数据。
4.EEPROM 数据寄存器- EEDR
• Bits 7..0 – EEDR7.0: EEPROM数据
对于 EEPROM 写操作, EEDR 是需要写到 EEAR 单元的数据;对于读操作, EEDR 是从地址 EEAR 读取的数据。
5.EEPROM 控制寄存器- EECR
• Bits 7..4 – Res:保留
保留位,读操作返回值为零。
• Bit 3 – EERIE: EEPROM 就绪中断使能
若 SREG 的 I 为 "1“,则置位 EERIE 使能 EEPROM 就绪中断。清零 EERIE 则禁止此中断。当 EEWE 清零时 EEPROM就绪中断即可发生。
• Bit 2 – EEMWE: EEPROM 主机写使能
EEMWE决定设置EEWE为"1“是否可以启动EEPROM写操作。。当EEMWE为"1“时,在4个时钟周期内置位 EEWE 将把数据写入 EEPROM 的指定地址;若 EEMWE 为 "0“,则EEWE 不起作用。EEMWE置位后 4 个周期,硬件对其清零。
• Bit 1 – EEWE: EEPROM写使能
当 EEPROM 数据和地址设置好之后,需置位 EEWE 以便将数据写入 EEPROM。此时EEMWE必须置位,否则EEPROM写操作将不会发生。写时序如下(第3和第4步不是必须的 ):
1. 等待 EEWE 为 0。2. 等待 SPMCSR 寄存器的 SPMEN为零。3. 将新的 EEPROM地址写入 EEAR。4. 将新的 EEPROM数据写入 EEDR。5. 对 EECR 寄存器的 EEMWE 写 "1“,同时清零 EEWE。6. 在置位 EEMWE的 4 个周期内,置位 EEWE。
在 CPU 写 Flash 存储器的时候不能对 EEPROM 进行编程。在启动 EEPROM 写操作之前软件必须要检查 Flash写操作是否已经完成。第二步仅在软件包含引导程序,允许CPU对 Flash 进行编程时才有用。如果 CPU 永远都不会写 Flash,则第二步可以忽略。请参考 P 255“ 支持引导装入程序 – 在写的同时可以读 (RWW, Read-While-Write) 的自我编程能力 ” 。
注意 : 如有中断发生于步骤 5 和 6 之间将导致写操作失败。因为此时 EEPROM 写使能操作将超时。如果一个操作EEPROM的中断打断了另一个EEPROM操作,EEAR或EEDR寄存器可能被修改,引起 EEPROM 操作失败。建议此时关闭全局中断标志 I。
经过写访问时间之后, EEWE 硬件清零。用户可以凭此位判断写时序是否已经完成。
EEWE 置位后, CPU 要停止两个时钟周期才会运行下一条指令。
• Bit 0 – EERE: EEPROM读使能
当 EEPROM地址设置好之后,需置位 EERE 以便将数据读入 EEAR。EEPROM数据的读取只需要一条指令,且无需等待。读取 EEPROM时 CPU 要停止 4 个时钟周期。
用户在读取 EEPROM 时应该检测 EEWE。如果一个写操作正在进行,就无法读取EEPROM,也无法改变寄存器 EEAR。标定振荡器用于 EEPROM访问定时。Table 2 为 CPU 访问 EEPROM 的典型时间。
下面的代码分别用汇编和C函数说明如何实现EEPROM的写操作。在此假设中断不会在执行这些函数的过程当中发生。例子同时还假设软件没有引导程序。若引导程序存在,则EEPROM 写函数还需要等待正在进行的 SPM 命令的结束。
下一个代码例子说明如何用汇编和C来读取EEPROM在此假设中断不会在执行这些函数的过程当中发生。
6.掉电休眠模式下EEPROM 的写入
当 EEPROM 执行写操作时进入掉电休眠模式, EEPROM 写操作继续,并在写访问时间结束前完成。但写操作结束后,振荡器继续工作,因此器件无法完全进入掉电模式。因此建议在进入掉电模式前检验 EEPROM写操作是否完成。
7.防止EEPROM 数据丢失
由于电源电压过低,CPU 和 EEPROM 有可能工作不正常,造成 EEPROM 数据的毁坏 (丢失 )。这种情况在使用独立的 EEPROM器件时也会遇到。
由于电压过低造成 EEPROM 数据损坏有两种可能:一是电压低于 EEPROM 写操作所需要的最低电压;二是 CPU 本身已经无法正常工作。
EEPROM 数据损坏的问题可以通过以下方法解决:
当电压过低时保持 AVR RESET 信号为低。这可以通过使能芯片的掉电检测电路 BOD 来实现。如果 BOD 电平无法满足要求,则可以使用外部复位电路。若写操作过程当中发生了复位,写操作将终止。
8.举例子
//***********************************************************************
// EEPROM读取函数*/
// addr:地址 number:长度 p_buff:读出数据存放指针
//***********************************************************************
void eprom_read(unsigned int addr, unsigned char number, unsigned char *p_buff)
{
while(EECR & (1 << EEWE)); //等待前面的写完成
EEARH = 0x00; //写高字节地址
while(number --)
{
EEARL = addr ++; //写地址低字节
EECR |= (1 << EERE); //读允许位置1
*p_buff++ = EEDR; //读出EEDR中的数据
}
}
//***********************************************************************
// EEPROM写入函数
// addr:地址 number:长度 p_buff:写入数据存放指针
//***********************************************************************
void eprom_write(unsigned int addr, unsigned char number, unsigned char *p_buff)
{
EEARH = 0x00;
while(number --)
{
while(EECR & (1 << EEWE)); //等待前面的写完成
EEARL = addr ++; //写地址
EEDR = *p_buff ++; //写数据到EEDR
EECR |= (1 << EEMWE); //主机写入允许位
EECR&=~(1<<EEWE);
EECR |= (1 << EEWE); //EEWE为1,执行写操作
}
}