资讯详情

治标治本,彻底解决AVR单片机EEPROM数据丢失问题

编译环境:Win-20060421+AVRStudio4.12.498ServicePack4 基本思路:每份写到EEPRM的数据,都做三个备份,每个备份的数据都做CRC16校验,只要系统运行中出错,错误地修改了数据, 那么根据校验字节就知道哪个备份的数据被修改了,然后用正确的备份覆盖出错的备份,达到数据恢复的目的。 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 */ #defineLID 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; }

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台