微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > AVR单片机内部EEPROM详解

AVR单片机内部EEPROM详解

时间:11-24 来源:互联网 点击:
AVR单片机内部EEPROM详解

使用EEPROM倒是挺简单的,无非是读和写操作,首先需要判断是否在读写中,判断读写忙标志,然后要保证读写时不能被打断即要关中断,接着要写入到写数据的地址,接着写数据,再将地址和数据控制位置位下,数据就写进了,最后别忘了开中断。读数据时,只要写入地址,然后将读控制位置位,再从寄存器EEDR中读出数据即可。

以上用法是简单用法,当然这种用法不能用在实际工程应用中的,因为写数据需要8ms的时间,系统当然不允许一直等待这8ms的,在本文下面介绍了一种比较好的方式,来安排系统工作的时间。当然前提是要理解清楚最简单的工作模式。

一、简单的工作模式

void EEPROM_write(unsigned int uiAddress,unsigned char ucData)
{
while(EECR&(1 //判断读写忙标志

CLI();
EEAR = uiAddress; //写入地址
EEDR = ucData; //送入数据
EECR |=(1 //地址和写控制位锁存,即可
EECR |=(1

SEI();
}

unsigned char EEPROM_read(unsigned int uiAddress)
{
while(EECR&(1 //判断读写忙标志

CLI();
EEAR = uiAddress; //送入地址
EECR |=(1 //读位置位

SEI();
return EEDR;//返回数据
}

读和写的操作如下面所示 读写数据时要从0x01开始 ,00地址有bug(数据手册上讲的)

temp=EEPROM_read(0x01);
EEPROM_write(0x01,temp);

二、提升篇-使用缓冲机构的操作

思路是这样的:首先建立读写缓冲区,把需要写的数据放入到写缓冲区中,由于在AVR单片机中,写一个数据时比较慢的大概要8ms吧,这么长的时间肯定不能一直while等下去,因此我们用中断在处理,等单片机EEPROM程序写好了就有ready中断,这时就能读写操作了,写的时候从写缓冲区中取出数据,写的时候要注意不允许读,经过一段时间后就完成了,而且我们发现写的时候只是把数据送入到单片机中的一个寄存器中,至于EEPROM什么时候来读这个寄存器直至写完,我们也没有必要管他,因为他操作好了会中断告诉我们,从而这8ms还可以用来执行其它的程序了,就这样直到所有的数据都写完了。

#pragma interrupt_handler vIvEeReady:iv_EE_READY
void vIvEeReady(void)
{
if(!fgEepromBufEmpty()) //缓冲区数据还没完全写到EPPROM中
{
CLI(); //写的时候不希望有别的中断
EEAR = _sEepromBuf[_bEepromBufRdPtr].wAddress;
EEDR = _sEepromBuf[_bEepromBufRdPtr].bVal; //数据写入
EECR |= BIT(EEMWE);
EECR |= BIT(EEWE);
SEI(); //写好这个就打开,尽可能满足实时性
_bEepromBufRdPtr++; //指向下一个缓冲数据
if(_bEepromBufRdPtr >= EEPROM_WRITE_BUF_SIZE) //到了缓冲区顶了
{
_bEepromBufRdPtr = 0; //从头部开始计数
}
_bEepromBufNs--; //当前还没有写入EEPROM的数
}
else
{
EECR &= ~BIT(EERIE); //都写好了就把中断关闭掉
}
}

uchar bWriteData2Eeprom(uint wAddress, uchar bVal)
{
if(fgEepromBufFull()) //是否达到缓冲定义的最大值
{
return RET_BUSY;
}

CLI(); //关中断?这里应该放在中断函数里面的
_sEepromBuf[_bEepromBufWrPtr].wAddress = wAddress;
_sEepromBuf[_bEepromBufWrPtr].bVal = bVal;
_bEepromBufWrPtr++;
if(_bEepromBufWrPtr >= EEPROM_WRITE_BUF_SIZE) //写满了就从头开始写
{ //需要保证数据不丢失
_bEepromBufWrPtr = 0;
}
_bEepromBufNs++; //写一个计数就加一下
EECR |= BIT(EERIE); //写一个数据后这里打开了中断
SEI();

return RET_SUCCESS;
}

// Notice! The programer must ensure the EEPROM is NOT in writing state.
uchar bReadDataFromEeprom(uint wAddress, uchar *pbVal)
{
if(EECR & BIT(EEWE)) //没有在写时才能读取,一般放在程序开始时
{
return RET_BUSY;
}

EEAR = wAddress; //送入地址
EECR |= BIT(EERE); //读锁存
*pbVal = EEDR; //取出数据
return RET_SUCCESS; //读取成功
}

BYTE bGetEepromWrBuf(void)
{
return _bEepromBufNs; //读取当前剩余的没写入的数据
}

void bClrEepromBuf(void)
{
CLI();
_bEepromBufNs = 0;
_bEepromBufRdPtr = _bEepromBufWrPtr;
EECR &= ~BIT(EERIE);
SEI();
}

BOOL fgEepromWizard(void)
{
BOOL fgRet = FALSE;

return fgRet;
}

void vInitEeprom(void)
{
EECR = 0x00; //EEPROM控制寄存器清零
_bEepromBufWrPtr = 0; //读写指针和数据计数清零
_bEepromBufRdPtr = 0;
_bEepromBufNs = 0;
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top