• 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,则地址仅会增加一个字节。
  • 相关阅读:
    将10进制数字转成62进制数字(转)
    admin添加用户时报错:(1452, 'Cannot add or update a child row: a foreign key constraint fails (`mxonline`.`django_admin_l
    Django admin 中抛出 'WSGIRequest' object has no attribute 'user'的错误
    分布式爬虫
    Scrapy之CrawlSpider
    Scrapy之Cookie和代理
    Scrapy核心组件
    scrapy之持久化存储
    Scrapy框架的基本使用
    爬虫之request模块高级
  • 原文地址:https://www.cnblogs.com/wolf-man/p/6761701.html
Copyright © 2020-2023  润新知