AVR(Mega32)读写内部EEPROM

开发工具:codeblocks+winAVR2010

方式一:(根据Atmega32资料)其实就两个函数——不知道为什么有时候成功又时候失败(不明所以);结合这两个读写函数,可以自己重写出其他读写一个block的函数

unsigned char EEPROM_read(unsigned int uiAddress)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEWE))
;
/* Set up address register */
EEAR = uiAddress;
/* Start eeprom read by writing EERE */
EECR |= (1<<EERE);
/* Return data from data register */
return EEDR;
}
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEWE))
;
/* Set up address and data registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMWE */
EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EEWE);
}

方式二:#include <avr/eeprom.h>借用其中定义好的函数

转自:http://blog.lixin.me/archives/29200/

在我使用的atmega16L的芯片中,包含 512 字节的 EEPROM 数据存储器。它是作为一个独立的数据空间而存在的。存储在EEPROM中的数据,在没有电的情况下下仍然可以保存,通俗的说类似电脑的硬盘。

EEPROM的访问需要涉及3个寄存器:地址寄存器、数据寄存器和控制寄存器。通过操作这3个寄存器来实现对EEPROM的操作。不过,在winavr中,已经提供了一个eeprom的操作类库给我们了,地址如下:

#include <avr/eeprom.h>

       该文件提供了几个函数,可以很方便地帮助我们完成对eeprom的操作。

eeprom_is_ready()

        这个函数返回一个布尔值,如果eeprom准备就绪的话会返回true。在对eeprom进行读写操作之前都应该先判断是否已经准备就绪。于是while(!eeprom_is_ready()){}这句话会出现在每个操作之前。

eeprom_busy_wait()

        这个函数其实是对上面eeprom_is_ready()的包装。正如上所说,每次都要先写一个while的等待不是个好方法,所以winavr就给包装一下。该函数的定义为:#define eeprom_busy_wait() do {} while (!eeprom_is_ready())

eeprom_write_byte(address,value)

        这个函数是向address这个eeprom地址写入一个字节。

eeprom_read_byte(address)

       这个函数是从address这个地址读取一个字节的内容。

其他函数如下:

Functions
• uint8_t eeprom_read_byte (const uint8_t __p) __ATTR_PURE__
• uint16_t eeprom_read_word (const uint16_t __p) __ATTR_PURE__
• uint32_t eeprom_read_dword (const uint32_t __p) __ATTR_PURE__
• float eeprom_read_float (const float __p) __ATTR_PURE__
• void eeprom_read_block (void __dst, const void __src, size_t __n)
• void eeprom_write_byte (uint8_t __p, uint8_t __value)
• void eeprom_write_word (uint16_t __p, uint16_t __value)
• void eeprom_write_dword (uint32_t __p, uint32_t __value)
• void eeprom_write_float (float __p, float __value)
• void eeprom_write_block (const void __src, void __dst, size_t __n)
• void eeprom_update_byte (uint8_t __p, uint8_t __value)
• void eeprom_update_word (uint16_t __p, uint16_t __value)
• void eeprom_update_dword (uint32_t __p, uint32_t __value)
• void eeprom_update_float (float __p, float __value)
• void eeprom_update_block (const void __src, void __dst, size_t __n)

接下来,来写一个简单的例子:

#include <avr/io.h>
#include <avr/eeprom.h>  //引入eeprom
#include <avr/interrupt.h> //中断使用

//外部中断0

ISR(INT0_vect){
eeprom_busy_wait();
eeprom_write_byte(1,0xf0); //向地址0x01写入数据0xf0
}

//外部中断1
ISR(INT1_vect){
eeprom_busy_wait();
PORTB=eeprom_read_byte(1); //从地址1读取数据并赋予PORTB
}
int main(void){
    cli();
    DDRB=0xff; //流水灯用的,设置为输出
    PORTB=0xff;  //输出高电平,led全灭
    DDRD=0xf3;//把两个中断用的端口设置为输入
    PORTD=0xff;
    GICR=0xc0;//中断0和中断1置位。
    MCUCR&=0xf0;//当低电平时触发中断
    sei();//开启全局中断使能。
    while(1);
}

上面的代码,我使用了PORTB作为led指示灯.并设置两个中断,低电位时触发。

实验方法是:

  1. 烧写程序入开发板。
  2. 按下按钮1,触发外部中断0,执行把0xf0数据写入eeprom中。
  3. 拔下电源,重新接通电源。
  4. 按下按钮2,触发外部中断1,执行从eeprom中读取数据,并通过led灯反馈结果。

不过在测试方式二的过程中,遇到一个小问题:http://blog.chinaunix.net/uid-11009175-id-4633984.html

今天在用codeblock打开几年前的avr工程,编译的时候,出错了,错误是 undefined reference to `__eewr_byte_m169p。
经过1个小时的努力,终于找到问题所在了。
解释:
As you see the EEPROM support has changed in recent years so that now the header files identify the AVR you are using (mega644) and then concatenate this onto the __eewr_byte_* style routine names and these are then provided in the link from the device specific .o file. When this works the map file shows something like:
e:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5\libc.a(eewr_byte_atmega644.o)
                              test.o (__eewr_byte_m644)
That's built on Windows with WinAVR but the point is that it's ../avr/lib/avr5/libc.a that is providing the function. If you get undefined ref then that suggests that you environment is not linking with the right libc.a
Maybe show your complete build output? Is the -mmcu=atmega644 being passed to the link as well as the compiles?

解决办法很简单,libc.a需要选择../avr/lib/avr5/libc.a这个才行。





  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值