http://blog.csdn.net/sdutake/article/details/9613989

在单片机系统开发中,系统配置参数通常需要永久存储在flash或者eeprom中。对于系统参数较多时,我们常常使用结构体来进行管理,如下面的实例,这是一个基于STM8系列单片机开发的某个产品的系统参数。这些参数被定义为系统配置结构体的成员变量。这些成员变量的类型都是不同的,所占的存储空间也不同。通过C语言中的sizeof关键词可以获得这个结构体类型的存储空间为42字节。

typedef struct

{  //关于系统时钟的变量

 //关于系统时钟的变量
  uint8_t second;
  uint8_t minute;
  uint8_t hour_12;
  uint8_t hour_24;
  uint8_t week;
  uint8_t date;
  uint8_t month;
  uint8_t year;
  TimeAP ap
 
//阀门开关标志
  BOOL IsValveOpen;
  ValveStatus ValveNowSts;
  //设置温度记录
  uint16_t TempSet;
  BOOL IsTempMode;
  //当前室内温度记录
  uint16_t TempNow;
  //热量及使用时间记录
  uint32_t HeatUsed;
  uint32_t TimeUsed
 
//自动开关模式及时间设置记录
  uint8_t OpenMin;
  uint8_t CloseMin;
  uint8_t OpenHour;
  uint8_t CloseHour;
  TimeAP OpenAp;
  TimeAP CloseAp;
  BOOL IsAutoMode;
//电池电量
  Battery BatLvl;
  //信号强度
  int8_t SgnStr;
  Signal SgnLvl;
  //地址
  uint8_t MeterAddr[7];
  //信道
  uint8_t Channel;
}SysData;
如何实现对以上的结构体数据进行存储和读取呢?即把完整的42字节的结构体变量存储在flash或eeprom中连续的42字节的存储空间中,读取时实现完整的变量读取,并且结构体中的成员变量也被正确赋值。
当然,你可以这么做:
依次取出结构体中每个成员,再依次存入flash或eeprom。读取方法相同。这样做不免费时费力。
利用结构体指针,只要几行代码就能实现了。
//编译环境:IAR Embedded Workbench for STMicroelectronics STM8 1.31 Evaluation
//单片机:STM8L15X系列
//对于flash和eeprom的底层操作代码使用了Atmel官方提供的单片机驱动库:stm8l15x_flash.c
#define SYS_DATA_ADDR           0x001200          //系统数据存储地址,在该款单片机中,这个地址实际上是属于eeprom的存储地址
//存储
void flashWriteSysData(SysData *data)
{
  uint8_t i = 0;
  uint8_t temp = 0;
  for(i=0;i<sizeof(*data);i++)
  {
    //结构体中的成员类型不是一定的,因此,通过内存访问的形式,将结构体中数据按照
    //字节依次取出,再写入eeprom。注意,使用结构体指针时,如果语句为:结构体首地址+1
    //则地址会增加整个结构体的长度。理论上不能使用地址增加的形式访问结构体成员。
    //如果需要特殊应用,则如下程序所示,先将结构体指针转换为uint8型指针,再通过
    //地址增加的形式,就可以每次增加一个字节的地址了。
    memcpy(&temp,((uint8_t *)(data))+i,1);                            //从结构体所在内存中拷贝一个byte
    FLASH_ProgramByte((SYS_DATA_ADDR+i),temp);            //写入这个byte
  }
}
//读取
void flashGetSysData(SysData *data)
{
  memcpy(data, (uint8_t *)SYS_DATA_ADDR, 41);
}
以上的实现方法利用了结构体指针。下面进行简单的分析:
入口参数“SysData *data”为结构体类型的指针,data指向该结构体的首地址。“data+1”则会使该指针地址向后跳过42字节。因为data是结构体类型的指针,而该结构体在内存中占用连续的42字节空间,并被认为是一个变量。那么如果指针+1,其指向的地址将会向后跳过一个完整的结构体存储空间,即42字节。
如果需要使用这个指针来依次访问该结构体的每一个成员变量,即每次指针+1,地址跳过1byte,则需要将该结构体类型的指针转换为unsigned char类型的指针:“(uint8_t *)(data)”,这时候再+1,则地址仅会增加一个字节。
原文地址:https://www.cnblogs.com/wolf-man/p/6761701.html