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,则地址仅会增加一个字节。