打印
[Atmel]

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

[复制链接]
811|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ddllxxrr|  楼主 | 2015-8-6 19:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

在项目中复制出来的程序,使用时可能有些地方需要修改。
编译环境:WinAVR-20060421 + AVR Studio 4.12.498  Service Pack 4


基本思路:每份写到EEPRM的数据,都做三个备份,每个备份的数据都做CRC16校验,只要系统运行中出错,错误地修改了EEPROM数据,
          那么根据校验字节就知道哪个备份的数据被修改了,然后用正确的备份覆盖出错的备份,达到数据恢复的目的。


EEPROMSave.h 文件:

/*   EEPROM管理定义   */

#define EepromPageSize        64                        //页容量定义

#define EepromPage0Addr        0x0000                        //各个页的其始地址定义
#define EepromPage1Addr        (EepromPage0Addr + EepromPageSize)
#define EepromPage2Addr        (EepromPage1Addr + EepromPageSize)
#define EepromPage3Addr        (EepromPage2Addr + EepromPageSize)
#define EepromPage4Addr        (EepromPage3Addr + EepromPageSize)
#define EepromPage5Addr        (EepromPage4Addr + EepromPageSize)
#define EepromPage6Addr        (EepromPage5Addr + EepromPageSize)
#define EepromPage7Addr        (EepromPage6Addr + EepromPageSize)

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

| 0 | 1 | 2 |        |.......................| 61 | 62 | 63 |
Data              Data...................Data.....CRCH CRCL
*/

#define VALID                                0x01
#define INVALID                                0x00

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


EEPROMSave.c 文件:

/*******************************************************************
*函数名称:EepromReadByte()
*函数功能:写一个Byte的数据进EEPROM
*输入参数:address:地址
*返回参数:从指定地址读出来的数据
*编写作者:my_avr
*编写时间:2007年8月13日
*相关说明:
********************************************************************/
unsigned char EepromReadByte(unsigned char *address)
{
        unsigned char data;
         
        data = 0;
         
        eeprom_busy_wait();
        data  = eeprom_read_byte(address);
         
        return data;
}

/*******************************************************************
*函数名称:EepromReadWord();
*函数功能:写一个Word的数据进EEPROM
*输入参数:address:地址
*返回参数:从指定地址读出来的数据
*编写作者:my_avr
*编写时间:2007年8月13日
*相关说明:
********************************************************************/
uint16_t EepromReadWord(uint16_t *address)
{
        uint16_t data;
         
        data = 0;
         
        eeprom_busy_wait();
        data  = eeprom_read_word(address);
         
        return data;
}

/*******************************************************************
*函数名称:EepromWriteByte()
*函数功能:写一个Byte的数据进EEPROM
*输入参数:address:地址;data:数据
*返回参数:无
*编写作者:my_avr
*编写时间:2007年8月13日
*相关说明:
********************************************************************/
void EepromWriteByte(unsigned char *address,unsigned char data)
{
        eeprom_busy_wait();
        eeprom_write_byte(address,data);
}

/*******************************************************************
*函数名称:EepromWriteWord()
*函数功能:写一个Word的数据进EEPROM
*输入参数:address:地址;data:数据
*返回参数:
*编写作者:my_avr
*编写时间:2007年8月13日
*相关说明:
********************************************************************/
void EepromWriteWord(unsigned int *address,unsigned int data)
{
        eeprom_busy_wait();
        eeprom_write_word(address,data);
}

/*******************************************************************
*函数名称:EepromWriteBlock()
*函数功能:将缓冲区中的n个数据写进EEPROM
*输入参数:address:地址;data:数据
*返回参数:
*编写作者:my_avr
*编写时间:2007年8月13日
*相关说明:
********************************************************************/
void EepromWriteBlock(unsigned char *buff,unsigned char *address,unsigned char n)
{
        unsigned char i;
         
        for (i = 0; i < n; i++)
        {
                EepromWriteByte((unsigned char *)(address + i),*buff);
                 
                buff++;
        }
}

/******************************************************************
*函数名称:unsigned char EepromCheck(unsigned char *pdata,unsigned char packsize)
*函数功能:检查EEPROM的数据是否有效,采用CRC16校验技术。
                  一次校验默认最后两个字节为校验码,
                  需要注意,packsize包括数据长度和校验码字节
*输入参数:pdata:数组指针;packsize:数据长度
*返回参数:数据是否有效,有效:VALID,无效:INVALID
*编写作者:my_avr
*编写时间:2007年8月21日
*相关说明:
********************************************************************/
unsigned char EepromCheck(unsigned char *pdata,unsigned char packsize)
{
        unsigned char i,j;
        unsigned int  crc,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)
        {
                return VALID;
        }
        else
        {
                return INVALID;
        }
}

/*******************************************************************
*函数名称:unsigned char CheckWriteCRC(unsigned char *pdata,unsigned char packsize)
*函数功能:为EEPROM数据写CRC校验码
*输入参数:pdata:数组指针;packsize:数据长度
*返回参数:操作成功否?,成功:VALID,失败:INVALID
*编写作者:my_avr
*编写时间:2007年8月21日
*相关说明:
********************************************************************/
unsigned char CheckWriteCRC(unsigned char *pdata,unsigned char packsize)
{
        unsigned char i,j;
        unsigned int  crc;
         
        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))
        {
                return VALID;
        }
        else
        {
                return INVALID;
        }
}

/********************************************************************
*函数名称:unsigned char CheckAllPage(void)
*函数功能:检查EEPROM数据是否有效,检查三个备份
*输入参数:无
*返回参数:操作成功否?,成功:VALID,失败:INVALID
*编写作者:my_avr
*编写时间:2007年8月21日
*相关说明:
********************************************************************/
uint8_t CheckAllPage(void)
{
        if ((EepromCheck((unsigned char *)EepromPage1Add,EepromPageSize) == VALID)
          &&(EepromCheck((unsigned char *)EepromPage2Add,EepromPageSize) == VALID)
          &&(EepromCheck((unsigned char *)EepromPage3Add,EepromPageSize) == VALID))
        {
                return VALID;
        }
         
        return INVALID;
}

/*******************************************************************
*函数名称:unsigned char DataRecover(void)
*函数功能:检查EEPROM数据是否被破坏,如果被破坏了,作数据恢复
*输入参数:无
*返回参数:操作成功否?,成功:VALID,失败:INVALID
*编写作者:my_avr
*编写时间:2007年8月21日
*相关说明:
********************************************************************/
uint8_t DataRecover(void)
{
        unsigned char i;
        unsigned char temp;
        unsigned char page;
        unsigned int  invalidpage[3];
        unsigned int  validpage;
         
        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

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://shop34182318.taobao.com/ http://shop562064536.taobao.com

2398

主题

6950

帖子

67

粉丝