新聞中心

EEPW首頁(yè) > EDA/PCB > 設(shè)計(jì)應(yīng)用 > avr eeprom保護(hù)方法.

avr eeprom保護(hù)方法.

作者: 時(shí)間:2024-05-10 來(lái)源:EDA365 收藏

在項(xiàng)目中復(fù)制出來(lái)的程序,使用時(shí)可能有些地方需要修改。
編譯環(huán)境:WinAVR-20060421+AVRStudio4.12.498ServicePack4
基本思路:每份寫到EEPRM的數(shù)據(jù),都做三個(gè)備份,每個(gè)備份的數(shù)據(jù)都做CRC16校驗(yàn),只要系統(tǒng)運(yùn)行中出錯(cuò),錯(cuò)誤地修改了數(shù)據(jù),
那么根據(jù)校驗(yàn)字節(jié)就知道哪個(gè)備份的數(shù)據(jù)被修改了,然后用正確的備份覆蓋出錯(cuò)的備份,達(dá)到數(shù)據(jù)恢復(fù)的目的。
Save.h文件:
#defineEepromPageSize 64 //頁(yè)容量定義
#defineEepromPage0Addr 0x0000 //各個(gè)頁(yè)的其始地址定義
#defineEepromPage1Addr (EepromPage0Addr+EepromPageSize)
#defineEepromPage2Addr (EepromPage1Addr+EepromPageSize)
#defineEepromPage3Addr (EepromPage2Addr+EepromPageSize)
#defineEepromPage4Addr (EepromPage3Addr+EepromPageSize)
#defineEepromPage5Addr (EepromPage4Addr+EepromPageSize)
#defineEepromPage6Addr (EepromPage5Addr+EepromPageSize)
#defineEepromPage7Addr (EepromPage6Addr+EepromPageSize)
#defineVALID 0x01
#defineINVALID 0x00
Save.c文件:
unsignedcharEepromReadByte(unsignedchar*address)
{
unsignedchardata;
data=0;
eeprom_busy_wait();
data=eeprom_read_byte(address);
returndata;
}
uint16_tEepromReadWord(uint16_t*address)
{
uint16_tdata;
data=0;
eeprom_busy_wait();
data=eeprom_read_word(address);
returndata;
}
voidEepromWriteByte(unsignedchar*address,unsignedchardata)
{
eeprom_busy_wait();
eeprom_write_byte(address,data);
}
voidEepromWriteWord(unsignedint*address,unsignedintdata)
{
eeprom_busy_wait();
eeprom_write_word(address,data);
}
voidEepromWriteBlock(unsignedchar*buff,unsignedchar*address,unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
{
EepromWriteByte((unsignedchar*)(address+i),*buff);
buff++;
}
}
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)
{
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;
}
}
uint8_tCheckAllPage(void)
{
if((EepromCheck((unsignedchar*)EepromPage1Add,EepromPageSize)==VALID)
&&(EepromCheck((unsignedchar*)EepromPage2Add,EepromPageSize)==VALID)
&&(EepromCheck((unsignedchar*)EepromPage3Add,EepromPageSize)==VALID))
{
returnVALID;
}
returnINVALID;
}
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) //三個(gè)備份都被破壞了
{
returnINVALID; //數(shù)據(jù)完全無(wú)效了
}
while((page--)>0) //數(shù)據(jù)恢復(fù)
{
for(i=0;i<EepromPageSize;i++)
{
temp=EepromReadByte((uint8_t*)(validpage+i));
EepromWriteByte((uint8_t*)(invalidpage[page]+i),temp);
}
}
if(CheckAllPage()==VALID)
{
returnVALID;
}
returnINVALID;
}
使用方法(三個(gè)備份):
1、定義一個(gè)數(shù)組:EEPROMData[EepromPageSize-2],數(shù)組定義為EepromPageSize-2是為了給每個(gè)備份留2個(gè)字節(jié)的校驗(yàn)
2、要保存數(shù)據(jù)時(shí),先把數(shù)據(jù)放到數(shù)組中,然后調(diào)用EepromWriteBlock()函數(shù),把這個(gè)數(shù)組的數(shù)據(jù)寫進(jìn)EEPROM,三個(gè)備份要寫三次。
3、寫完了之后,調(diào)用CheckWriteCRC()函數(shù),該函數(shù)會(huì)計(jì)算出當(dāng)前備份的CRC16檢驗(yàn)數(shù)據(jù)并寫到EEPROM備份的尾部,有多少個(gè)備份就要調(diào)用多少次。
4、至此,數(shù)據(jù)的備份工作已經(jīng)完成。
5、校驗(yàn)數(shù)據(jù)(一般在復(fù)位后運(yùn)行),執(zhí)行CheckAllPage()函數(shù),若通過了,則EEPROM數(shù)據(jù)沒有問題,否則要運(yùn)行DataRecover()函數(shù),對(duì)損壞的備份進(jìn)行修復(fù)

本文引用地址:http://2s4d.com/article/202405/458561.htm


關(guān)鍵詞: EEPROM avr

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉