硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5312|回复: 26
收起左侧

各种数据类型编程EEPROM,SPI Flash等存储器的简易方法

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2019-2-14 02:26:17 | 显示全部楼层 |阅读模式
一般这些存储器都是字节编程,写入浮点等数据类型时不太方便。

这里分享一个方法,定义一个结构体,将各种数据类型封装进去
  1. /* 全局参数 */
  2. typedef struct
  3. {
  4.         uint32_t ParamVer;                        /* 参数区版本控制(可用于程序升级时,决定是否对参数区进行升级) */

  5.         /* LCD背光亮度 */
  6.         uint8_t ucBackLight;

  7.         /* 触摸屏校准参数 */
  8.         //{
  9.                 uint8_t TouchDirection;        /* 屏幕方向 0-3  0表示横屏,1表示横屏180° 2表示竖屏 3表示竖屏180° */
  10.                
  11.                 uint8_t XYChange;                /* X, Y 是否交换, 1表示i切换,0表示不切换  */
  12.                
  13.                 uint16_t usAdcX1;        /* 左上角 */
  14.                 uint16_t usAdcY1;
  15.                 uint16_t usAdcX2;        /* 右下角 */
  16.                 uint16_t usAdcY2;
  17.                 uint16_t usAdcX3;        /* 左下角 */
  18.                 uint16_t usAdcY3;
  19.                 uint16_t usAdcX4;        /* 右上角 */
  20.                 uint16_t usAdcY4;
  21.                
  22.                 uint16_t usLcdX1;        /* 校准时,屏幕坐标 */
  23.                 uint16_t usLcdY1;        /* 校准时,屏幕坐标 */
  24.                 uint16_t usLcdX2;        /* 校准时,屏幕坐标 */
  25.                 uint16_t usLcdY2;        /* 校准时,屏幕坐标 */
  26.                 uint16_t usLcdX3;        /* 校准时,屏幕坐标 */
  27.                 uint16_t usLcdY3;        /* 校准时,屏幕坐标 */
  28.                 uint16_t usLcdX4;        /* 校准时,屏幕坐标 */
  29.                 uint16_t usLcdY4;        /* 校准时,屏幕坐标 */        
  30.         //}
  31.         
  32.         /* uip ip 地址参数 */
  33.         uint8_t uip_ip[4];                  /* 本机IP地址 */
  34.         uint8_t uip_net_mask[4];       /* 子网掩码 */
  35.         uint8_t uip_gateway[4];        /* 默认网关 */

  36.         /* lwip ip 地址参数 */
  37.         uint8_t lwip_ip[4];               /* 本机IP地址 */
  38.         uint8_t lwip_net_mask[4];    /* 子网掩码 */
  39.         uint8_t lwip_gateway[4];      /* 默认网关 */

  40.         /* 收音机参数 */
  41.         uint8_t ucRadioMode;           /* AM 或 FM */
  42.         uint8_t ucRadioListType;       /* 电台列表类型。武汉地区或全国 */
  43.         uint8_t ucIndexFM;              /* 当前FM电台索引 */
  44.         uint8_t ucIndexAM;              /* 当前电台索引 */
  45.         uint8_t ucRadioVolume;        /* 音量 */
  46.         uint8_t ucSpkOutEn;            /* 扬声器输出使能 */
  47.         
  48.         uint8_t Addr485;
  49.         uint32_t Baud485;
  50. }
  51. PARAM_T;
复制代码



读取数据:
2.jpg

写入数据:
1.jpg


回复

使用道具 举报

14

主题

207

回帖

254

积分

高级会员

积分
254
发表于 2019-2-14 10:34:14 | 显示全部楼层
程序可读性能提高很多,赞
回复

使用道具 举报

2

主题

569

回帖

575

积分

金牌会员

积分
575
发表于 2019-2-15 08:40:52 | 显示全部楼层
嗯 平时做项目都是这么干的
回复

使用道具 举报

0

主题

28

回帖

28

积分

新手上路

积分
28
发表于 2019-2-15 09:29:45 | 显示全部楼层
平时做项目也是这么干的
回复

使用道具 举报

0

主题

13

回帖

13

积分

新手上路

积分
13
发表于 2019-2-20 10:09:32 | 显示全部楼层

不错,挺好的!
回复

使用道具 举报

5

主题

179

回帖

194

积分

初级会员

积分
194
发表于 2019-2-27 09:47:37 | 显示全部楼层
使用方法一样
回复

使用道具 举报

11

主题

31

回帖

64

积分

初级会员

积分
64
发表于 2019-8-14 08:54:54 | 显示全部楼层
好方法,顺便问一下,写入数据后eeprom是不是一般会加上检验码,每次写入的地址是不是要换一下,确保不会容易被写坏?
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2019-8-14 09:52:59 | 显示全部楼层
提线木偶 发表于 2019-8-14 08:54
好方法,顺便问一下,写入数据后eeprom是不是一般会加上检验码,每次写入的地址是不是要换一下,确保不会容 ...

看你实际应用中写入擦除的频率了。。。。
一般情况下,eeprom的寿命时足够的。几万次把。 保证5年有效就差不多了。
电力系统应用中,都是一个数据存储3份,然后两两比较进行校验。足够安全了。
回复

使用道具 举报

11

主题

31

回帖

64

积分

初级会员

积分
64
发表于 2019-8-14 11:03:29 | 显示全部楼层
caicaptain2 发表于 2019-8-14 09:52
看你实际应用中写入擦除的频率了。。。。
一般情况下,eeprom的寿命时足够的。几万次把。 保证5年有效就 ...

好的,谢谢
回复

使用道具 举报

11

主题

31

回帖

64

积分

初级会员

积分
64
发表于 2019-8-14 11:06:02 | 显示全部楼层
caicaptain2 发表于 2019-8-14 09:52
看你实际应用中写入擦除的频率了。。。。
一般情况下,eeprom的寿命时足够的。几万次把。 保证5年有效就 ...

小数可以直接用uint32类型吗,都是4字节
回复

使用道具 举报

34

主题

111

回帖

213

积分

高级会员

程序小白

积分
213
QQ
发表于 2020-12-2 11:28:51 | 显示全部楼层
自己搞得板子上,没有画EEROM,只留了一个SPI FLASH 。  如果用 SPI FLASH存储校准数据,会有什么问题吗? 难道可能 会丢数据?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
 楼主| 发表于 2020-12-2 12:03:18 | 显示全部楼层
清风徐来 发表于 2020-12-2 11:28
自己搞得板子上,没有画EEROM,只留了一个SPI FLASH 。  如果用 SPI FLASH存储校准数据,会有什么问题吗?  ...

也可以的,主要是EEPROM更加经久耐操,一般关键场合用EERPOM存储关键数据的多。
回复

使用道具 举报

10

主题

17

回帖

47

积分

新手上路

积分
47
发表于 2020-12-11 08:37:17 | 显示全部楼层
如果结构体里面的变量不是所有都需要存储的呢?怎么可以只存储和读取部分变量?
回复

使用道具 举报

45

主题

70

回帖

205

积分

高级会员

积分
205
发表于 2020-12-24 14:56:29 | 显示全部楼层
这个结构体里可以放浮点数之类的吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
 楼主| 发表于 2020-12-25 09:12:41 | 显示全部楼层
chinashaoshu 发表于 2020-12-24 14:56
这个结构体里可以放浮点数之类的吗?

可以的。
回复

使用道具 举报

7

主题

23

回帖

44

积分

新手上路

积分
44
发表于 2021-1-6 17:52:03 | 显示全部楼层
看您这种写法都是整个读出来整个写进去,如果只需要读取或者修改结构体里面的部分参数,这个要怎么弄?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
 楼主| 发表于 2021-1-7 08:02:42 | 显示全部楼层
jacksimcom 发表于 2021-1-6 17:52
看您这种写法都是整个读出来整个写进去,如果只需要读取或者修改结构体里面的部分参数,这个要怎么弄?

也是整体写入,整体更新。
回复

使用道具 举报

6

主题

92

回帖

110

积分

初级会员

积分
110
发表于 2021-1-7 09:30:54 | 显示全部楼层
我一直都是这么做的,但是我会在前面加一个校验

typedef __packed struct
{
    uint16_t CRC16;
    uint16_t length;
    uint16_t counter;
} TParameterSetHeader;

typedef __packed struct
{
    TParameterSetHeader Header;
    ......
} TParameterSetOperaConfig;

并且做备份处理,这样保证数据万无一失

#define MPARSET(n, p, t, d)                     {n, p, t, d},

typedef struct MParSet_struct
{
    uint8_t  Type;
    uint8_t  *ParSet;
    uint16_t Length;
    uint8_t  StoreDouble;
} TMParSet;

const TMParSet ParSets[] =
{   /*      Type                             *ParSet                         Length                      StoreDouble */
        MPARSET(PARSET_TYPE_PARSET_OPERACONFIG,  (uint8_t *)&ParSetOperaConfig,  sizeof(ParSetOperaConfig),  1)
        MPARSET(PARSET_TYPE_PARSET_PRODUCTION,   (uint8_t *)&ParSetProduction,   sizeof(ParSetProduction),   1)
};
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
 楼主| 发表于 2021-1-8 08:38:26 | 显示全部楼层
solita 发表于 2021-1-7 09:30
我一直都是这么做的,但是我会在前面加一个校验

typedef __packed struct

不错
回复

使用道具 举报

1

主题

23

回帖

26

积分

新手上路

积分
26
发表于 2021-1-18 17:55:31 | 显示全部楼层
好东西
回复

使用道具 举报

34

主题

111

回帖

213

积分

高级会员

程序小白

积分
213
QQ
发表于 2021-2-24 13:52:02 | 显示全部楼层
24C256 这类EEROM,默认存储的值 是 0X00  还是 0XFF ?   我调试的板子的,初始值是乱,不知道问题出在哪?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
 楼主| 发表于 2021-2-24 14:08:37 | 显示全部楼层
清风徐来 发表于 2021-2-24 13:52
24C256 这类EEROM,默认存储的值 是 0X00  还是 0XFF ?   我调试的板子的,初始值是乱,不知道问题出在哪?

EEPROM不需要擦除,直接修改即可,所以不存在初始值的问题
回复

使用道具 举报

4

主题

16

回帖

28

积分

新手上路

积分
28
发表于 2021-3-6 15:27:32 | 显示全部楼层
这样封装之后,是不是sizeof的大小会超过各分量加起来的总和。占用的Flash空间会大一点?
串口发送的话是不是也会存在多余的无效字节?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
 楼主| 发表于 2021-3-6 15:47:18 | 显示全部楼层
样时代 发表于 2021-3-6 15:27
这样封装之后,是不是sizeof的大小会超过各分量加起来的总和。占用的Flash空间会大一点?
串口发送的话是 ...

可以给结构体加上关键词__packed解决此问题。

不过加不加无所谓,多占用了不了多少,串口接收端也定义相应结构体接收即可
回复

使用道具 举报

2

主题

43

回帖

54

积分

初级会员

积分
54
发表于 2021-3-24 10:05:16 | 显示全部楼层
顶一个,一直没有过这种想法,前辈们的经验果然十足。每次写EEPROM都是自己拆分成字节,然后一点一点写入,没想到还有结构体这种写入的方法。大开眼界!
回复

使用道具 举报

13

主题

57

回帖

96

积分

初级会员

积分
96
发表于 2021-4-6 10:57:37 | 显示全部楼层
jacksimcom 发表于 2021-1-6 17:52
看您这种写法都是整个读出来整个写进去,如果只需要读取或者修改结构体里面的部分参数,这个要怎么弄?

可以获取单个元素的地址
#define Param_Item(item)   ((u32)(&(((g_tParam *)0)->item)) + STORE_ADDR_BEGIN)
Param_Item(ParamVer)
回复

使用道具 举报

5

主题

17

回帖

32

积分

新手上路

积分
32
发表于 2021-11-11 16:38:48 | 显示全部楼层
经典方法,可移植性很强
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 07:22 , Processed in 0.261091 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表