彻底解决AVR单片机EEPROM数据丢失问题

来源:本站
导读:目前正在解读《彻底解决AVR单片机EEPROM数据丢失问题》的相关信息,《彻底解决AVR单片机EEPROM数据丢失问题》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《彻底解决AVR单片机EEPROM数据丢失问题》的详细说明。
简介:基本思路:每份写到EEPRM的数据,都做三个备份,每个备份的数据都做CRC16校验,只要系统运行中出错,错误地修改了EEPROM数据,那么根据校验字节就知道哪个备份的数据被修改了,然后用正确的备份覆盖出错的备份,达到数据恢复的目的。

编译环境:WinAVR-20060421+AVRStudio4.12.498ServicePack4

EEPROMSave.h文件:

/*EEPROM管理定义*/

#defineEepromPageSize 64 //页容量定义

#defineEepromPage0Addr 0x0000 //各个页的其始地址定义

#defineEepromPage1Addr (EepromPage0Addr+EepromPageSize)

#defineEepromPage2Addr (EepromPage1Addr+EepromPageSize)

#defineEepromPage3Addr (EepromPage2Addr+EepromPageSize)

#defineEepromPage4Addr (EepromPage3Addr+EepromPageSize)

#defineEepromPage5Addr (EepromPage4Addr+EepromPageSize)

#defineEepromPage6Addr (EepromPage5Addr+EepromPageSize)

#defineEepromPage7Addr (EepromPage6Addr+EepromPageSize)

/*

最后两个字节为CRC16校验码,其余为数据

|0|1|2| |.......................|61|62|63|

Data Data...................Data.....CRCHCRCL

*/

#defineVALID 0x01

#defineINVALID 0x00

/*-----------------------------------------------------------------------------------------*/

EEPROMSave.c文件:

/*******************************************************************

*函数名称:EepromReadByte()

*函数功能:写一个Byte的数据进EEPROM

*输入参数:address:地址

*返回参数:从指定地址读出来的数据

*编写作者:my_avr

*编写时间:2007年8月13日

*相关说明:

********************************************************************/

unsignedcharEepromReadByte(unsignedchar*address)

{

unsignedchardata;

data=0;

eeprom_busy_wait();

data=eeprom_read_byte(address);

returndata;

}

/*******************************************************************

*函数名称:EepromReadWord();

*函数功能:写一个Word的数据进EEPROM

*输入参数:address:地址

*返回参数:从指定地址读出来的数据

*编写作者:my_avr

*编写时间:2007年8月13日

*相关说明:

********************************************************************/

uint16_tEepromReadWord(uint16_t*address)

{

uint16_tdata;

data=0;

eeprom_busy_wait();

data=eeprom_read_word(address);

returndata;

}

/*******************************************************************

*函数名称:EepromWriteByte()

*函数功能:写一个Byte的数据进EEPROM

*输入参数:address:地址;data:数据

*返回参数:无

*编写作者:my_avr

*编写时间:2007年8月13日

*相关说明:

********************************************************************/

voidEepromWriteByte(unsignedchar*address,unsignedchardata)

{

eeprom_busy_wait();

eeprom_write_byte(address,data);

}

/*******************************************************************

*函数名称:EepromWriteWord()

*函数功能:写一个Word的数据进EEPROM

*输入参数:address:地址;data:数据

*返回参数:

*编写作者:my_avr

*编写时间:2007年8月13日

*相关说明:

********************************************************************/

voidEepromWriteWord(unsignedint*address,unsignedintdata)

{

eeprom_busy_wait();

eeprom_write_word(address,data);

}

/*******************************************************************

*函数名称:EepromWriteBlock()

*函数功能:将缓冲区中的n个数据写进EEPROM

*输入参数:address:地址;data:数据

*返回参数:

*编写作者:my_avr

*编写时间:2007年8月13日

*相关说明:

********************************************************************/

voidEepromWriteBlock(unsignedchar*buff,unsignedchar*address,unsignedcharn)

{

unsignedchari;

for(i=0;i<n;i++)

{

EepromWriteByte((unsignedchar*)(address+i),*buff);

buff++;

}

}

/******************************************************************

*函数名称:unsignedcharEepromCheck(unsignedchar*pdata,unsignedcharpacksize)

*函数功能:检查EEPROM的数据是否有效,采用CRC16校验技术。

一次校验默认最后两个字节为校验码,

需要注意,packsize包括数据长度和校验码字节

*输入参数:pdata:数组指针;packsize:数据长度

*返回参数:数据是否有效,有效:VALID,无效:INVALID

*编写作者:my_avr

*编写时间:2007年8月21日

*相关说明:

********************************************************************/

unsignedcharEepromCheck(unsignedchar*pdata,unsignedcharpacksize)

{

unsignedchari,j;

unsignedintcrc,ref_crc;

crc=0;

ref_crc=0;

for(i=0;i<(packsize-2);i++)

{

crc=crc^((uint16_t)EepromReadByte(pdata)<<8);

for(j=0;j<8;j++)

{

if(crc&0x8000)

{

crc=(crc<<1)^0x1021;

}

else

{

crc=crc<<1;

}

}

pdata++;

}

ref_crc=(uint16_t)EepromReadByte(pdata);

ref_crc=ref_crc<<8;

pdata++;

ref_crc|=(uint16_t)EepromReadByte(pdata);

if(crc==ref_crc)

{

returnVALID;

}

else

{

returnINVALID;

}

}

/*******************************************************************

*函数名称:unsignedcharCheckWriteCRC(unsignedchar*pdata,unsignedcharpacksize)

*函数功能:为EEPROM数据写CRC校验码

*输入参数:pdata:数组指针;packsize:数据长度

*返回参数:操作成功否?,成功:VALID,失败:INVALID

*编写作者:my_avr

*编写时间:2007年8月21日

*相关说明:

********************************************************************/

unsignedcharCheckWriteCRC(unsignedchar*pdata,unsignedcharpacksize)

{

unsignedchari,j;

unsignedintcrc;

crc=0;

for(i=0;i<(packsize-2);i++)

{

crc=crc^((uint16_t)EepromReadByte(pdata)<<8);

for(j=0;j<8;j++)

{

if(crc&0x8000)

{

crc=(crc<<1)^0x1021;

}

else

{

crc=crc<<1;

}

}

pdata++;

}

EepromWriteByte(pdata,(uint8_t)(crc>>8));

pdata++;

EepromWriteByte(pdata,(uint8_t)crc);

pdata++;

if(EepromCheck((pdata-packsize),packsize))

{

returnVALID;

}

else

{

returnINVALID;

}

}

/********************************************************************

*函数名称:unsignedcharCheckAllPage(void)

*函数功能:检查EEPROM数据是否有效,检查三个备份

*输入参数:无

*返回参数:操作成功否?,成功:VALID,失败:INVALID

*编写作者:my_avr

*编写时间:2007年8月21日

*相关说明:

********************************************************************/

uint8_tCheckAllPage(void)

{

if((EepromCheck((unsignedchar*)EepromPage1Add,EepromPageSize)==VALID)

&&(EepromCheck((unsignedchar*)EepromPage2Add,EepromPageSize)==VALID)

&&(EepromCheck((unsignedchar*)EepromPage3Add,EepromPageSize)==VALID))

{

returnVALID;

}

returnINVALID;

}

/*******************************************************************

*函数名称:unsignedcharDataRecover(void)

*函数功能:检查EEPROM数据是否被破坏,如果被破坏了,作数据恢复

*输入参数:无

*返回参数:操作成功否?,成功:VALID,失败:INVALID

*编写作者:my_avr

*编写时间:2007年8月21日

*相关说明:

********************************************************************/

uint8_tDataRecover(void)

{

unsignedchari;

unsignedchartemp;

unsignedcharpage;

unsignedintinvalidpage[3];

unsignedintvalidpage;

invalidpage[0]=0;

invalidpage[1]=0;

invalidpage[2]=0;

validpage=0;

temp=0;

page=0;

if(EepromCheck((uint8_t*)EepromPage1Add,EepromPageSize)==VALID)

{

validpage=EepromPage1Add;

}

else

{

invalidpage[page]=EepromPage1Add;

page++;

}

if(EepromCheck((uint8_t*)EepromPage2Add,EepromPageSize)==VALID)

{

validpage=EepromPage2Add;

}

else

{

invalidpage[page]=EepromPage2Add;

page++;

}

if(EepromCheck((uint8_t*)EepromPage3Add,EepromPageSize)==VALID)

{

validpage=EepromPage3Add;

}

else

{

invalidpage[page]=EepromPage3Add;

page++;

}

if(page==3) //三个备份都被破坏了

{

returnINVALID; //数据完全无效了

}

while((page--)>0) //数据恢复

{

for(i=0;i<EepromPageSize;i++)

{

temp=EepromReadByte((uint8_t*)(validpage+i));

EepromWriteByte((uint8_t*)(invalidpage[page]+i),temp);

}

}

if(CheckAllPage()==VALID)

{

returnVALID;

}

returnINVALID;

}

使用方法(三个备份):

1、定义一个数组:EEPROMData[EepromPageSize-2],数组定义为EepromPageSize-2是为了给每个备份留2个字节的校验

2、要保存数据时,先把数据放到数组中,然后调用EepromWriteBlock()函数,把这个数组的数据写进EEPROM,三个备份要写三次。

3、写完了之后,调用CheckWriteCRC()函数,该函数会计算出当前备份的CRC16检验数据并写到EEPROM备份的尾部,有多少个备份就要调用多少次。

4、至此,数据的备份工作已经完成。

5、校验数据(一般在复位后运行),执行CheckAllPage()函数,若通过了,则EEPROM数据没有问题,否则要运行DataRecover()函数,对损坏的备份进行修复

------------------修改原因:修改变量的定义形式

提醒:《彻底解决AVR单片机EEPROM数据丢失问题》最后刷新时间 2024-03-14 01:09:23,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《彻底解决AVR单片机EEPROM数据丢失问题》该内容的真实性请自行鉴别。