STM32L0中操作EEPROM本来参考了上篇操作FLASH的方法,多多少少都有些问题。我觉得可能是结构体在转换成其他变量的时候出了问题。

比如下面这段代码,在Windows上可以正常运行(使用g++编译),但是在单片机上就会卡死。

typedef struct
{
uint8_t IDD;
uint8_t zero[4];
uint8_t dutyCorr[4];
} usrflash; usrflash eepromDat = {.IDD = 1U, .zero = {0}, .dutyCorr = {0}}; int main()
{
float zerof = 3.14;
uint8_t zeroc[4] = {0};
float zero = 0;
eepromDat.zero[0] = *((uint8_t *)&zerof + 0);
eepromDat.zero[1] = *((uint8_t *)&zerof + 1);
eepromDat.zero[2] = *((uint8_t *)&zerof + 2);
eepromDat.zero[3] = *((uint8_t *)&zerof + 3);
zero = *(float *)(&eepromDat)->zero;
printf("\r\nzero=%f\r\n\n", zero);
return 0;
}

这段代码的大义是将 zerof 这个变量打散储存在结构体的一个数组里,然后再还原出来。其在Windows上毫无问题,但若要再单片机上运行就必须创建一个中间变量将eepromDat.zero[0~3]的值先赋给中间变量再利用中间变量还原那个浮点数。总的来说就是单片机,结构体,不行

	float zerof = 3.14;
uint8_t p_time[4] = {0};
float zero = 0;
eepromDat.zero[0] = *((uint8_t *)&zerof + 0);
eepromDat.zero[1] = *((uint8_t *)&zerof + 1);
eepromDat.zero[2] = *((uint8_t *)&zerof + 2);
eepromDat.zero[3] = *((uint8_t *)&zerof + 3);
p_time[0] = eepromDat.zero[0];
p_time[1] = eepromDat.zero[1];
p_time[2] = eepromDat.zero[2];
p_time[3] = eepromDat.zero[3];
zero = *(float*)p_time;
printf("\r\nzero=%f\r\n\n", zero);

造成这种问题的原因我也没想明白,但我隐约觉得这事没准和编译器有关系,也许ARM-GCC可以解决。这是我第一次对ARM-CC提出质疑。

将结构体与字符串进行相互转换

为了应对以上的问题,我想到的办法是干脆先将结构体数据转换成字符串,再将字符串储存进 EEPROM 就要方便的多了。这样只各需要一个在 EEPROM 中读写字符串的函数就可以同时操作字符串和结构体了。

而且字符串是 char* , 其是由字节组成的,又因为byte「字节」是内存寻址和存取的最小单位,最起码这样看上去要安全一些。

对于结构体的要求

若想将结构体顺利的准换成字符串,对于结构体还是有一定要求的,一般要求结构体的形式如下

typedef struct
{
uint8_t IDD;
float zero;
float dutyCorr;
...............
} usrflash;

其中第一个成员变量的变量名和变量类型千万不要修改,因为在将结构体转换为字符串是是要以它的第一个成员变量的地址作为开头的。

将结构体转换成字符串的方法

其实就是指针的灵活运用

// eepromDat 是 usrflash 类型的结构体

uint8_t *p_temp = (uint8_t *)malloc(sizeof(usrflash));
for (uint8_t i = 0; i < sizeof(usrflash); i++)
{
p_temp[i] = *((uint8_t *)((&(&eepromDat)->IDD) + i));
}
free(p_temp);

将字符串还原为结构体的方法

// eepromDat2 是 usrflash 类型的结构体

uint8_t *q_temp = (uint8_t *)malloc(sizeof(usrflash));
for (uint8_t i = 0; i < sizeof(usrflash); i++)
{
*(uint8_t *)(&((&eepromDat2)->IDD) + i) = *(q_temp + i);
}
free(q_temp);

以字符串作为中间量的EEPROM中结构体的读写操作

    /* 向 EEPROM 中写结构体 ------------------------------------------- */
// 待写入的结构体
usrflash eepromDat;
// 为中间缓存(字符串)分配内存
uint8_t *p_temp = (uint8_t *)malloc(sizeof(usrflash));
// 将结构体转换成字符串
for (uint8_t i = 0; i < sizeof(usrflash); i++)
{
p_temp[i] = *((uint8_t *)((&(&eepromDat)->IDD) + i));
}
// 将字符串写入 EEPROM
FLASH_EEPROM_Write_string(EEPROM_BASE_ADDR, p_temp, sizeof(usrflash));
// 释放内存
free(p_temp); /* 从 EEPROM 中读结构体 ------------------------------------------- */
// 待存入的结构体
usrflash eepromDat2;
// 为中间缓存(字符串)分配内存
uint8_t *q_temp = (uint8_t *)malloc(sizeof(usrflash));
// 从 EEPROM 中读取字符串
FLASH_EEPROM_Read_string(EEPROM_BASE_ADDR, q_temp, sizeof(usrflash));
// 将字符串转换为结构体
for (uint8_t i = 0; i < sizeof(usrflash); i++)
{
*(uint8_t *)(&((&eepromDat2)->IDD) + i) = *(q_temp + i);
}
// 释放内存
free(q_temp);

EEPROM 函数。在别的文件中摘录

 void FLASH_EEPROM_Write_string(uint32_t addr, uint8_t * p_temp, uint16_t len)
{
HAL_FLASHEx_DATAEEPROM_Unlock();
for (uint16_t i = 0; i < len; i++)
{
HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, addr + i, *((uint8_t *)(p_temp + i)));
}
HAL_FLASHEx_DATAEEPROM_Lock();
}
void FLASH_EEPROM_Read_string(uint32_t addr, uint8_t * q_temp, uint16_t len)
{
for (uint16_t i = 0; i < len; i++)
{
*((uint8_t *)(q_temp + i)) = *(uint8_t *)(addr + i);
}
}

禁止转载到 CSDN !

禁止转载到 CSDN !

禁止转载到 CSDN !

STM32L0系列EEPROM中结构体的读取的更多相关文章

  1. C语言中结构体对齐问题

    C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...

  2. C++中 结构体和类的异同

    在C++中,结构体是一种特殊形态的类. 结构体和类的唯一区别就是:  结构体和类具有不同的默认访问控制属性. 类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型(private) 结构体中, ...

  3. C语言中结构体赋值问题的讨论

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  4. OC中结构体作为对象属性

    在OC中结构体有时候也作为对象的属性 类的定义 #import <Foundation/Foundation.h> typedef struct{ int year; int month; ...

  5. (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换

    一个工作任务涉及到c#与c++系统间的udp通信,处理了蛮长时间没有完成任务,但是期间接触到不少小知识点.本人是初接触c#,c++语言没有接触过.可能写的东西都很小儿科,暂且记录下来当工作日记把. 先 ...

  6. C C++ 中结构体与类

    先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错 1>d:\myproject\visual studio 2013\projects\myc++\main.c(71 ...

  7. C语言中结构体赋值问题的讨论(转载)

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  8. C中结构体的存储分配

    C中结构体的存储分配 对于C语言中结构体所占的存储空间的大小,也一直是笔试面试的常客,今天好好看了一下这方面,以前一直以为很清楚了,今天通过各种实际测试举例,发现原来还是没有搞透彻,好在现在是彻底懂了 ...

  9. C /C ++中结构体的定义

    c语言中结构体的定义: struct 结构体名{ 成员列表: ..... }结构体变量: 7.1.1 结构体类型变量的定义结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对问 ...

随机推荐

  1. git根据项目地址使用不同代理服务器

    问题 由于公司访问GitHub只能走代理,但是内网gitlab服务器又不能走代理. 因此想找到一种方案,可以支持git自动根据项目地址使用不同代理. 方案 如下所示,可以指定GitHub地址使用指定的 ...

  2. OSI网络参考模型学习

    文章目录 一.计算机与网络的发展 1.1 批处理系统 1.2 分时系统 1.3 计算机之间的通信 1.4 基于分组交换技术的计算机网络 1.5 互联网时代的计算机网络 1.6 计算机网络中协议的规定 ...

  3. 【文件格式探究】EP.1 对ePub文件格式的初探

    这是"文件格式探究"专题的第 1 期--初探 "ePub" 文件格式.这个专题将会给各位读者呈现笔者探索各种文件格式的过程,具体则是文件的内容是如何呈现出来的. ...

  4. 如何修改leaflet的marker图标

    1. 从官网中查看对应文档:https://leafletjs.com/ 2. 3. var greenIcon = L.icon({ iconUrl: 'leaf-green.png', shado ...

  5. 关于Ubuntu18.04 linux系统使用安装JDK Mysql

    平台部署 一.安装JDK step1.下载OracleJDKstep2. 解压step3. 加入环境变量 具体操作如下: lemon@ubuntu:~$ cd ~/download/ lemon@ub ...

  6. SpringCloud升级之路2020.0.x版-24.测试Spring Cloud LoadBalancer

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 通过单元测试,我们 ...

  7. WAMP 2.5 无法访问局域网的解决方法

    打开Apache配置文件 httpd.conf  (该文件在wamp\bin\apache\apache2.4.9\conf) DocumentRoot "d:/wamp/www/" ...

  8. Spring BeanDefinition

    定义 /** * A BeanDefinition describes a bean instance, which has property values, * constructor argume ...

  9. K8s 系列(三) - 如何配置 etcd https 证书?

    在 K8s 中,kube-apiserver 使用 etcd 对 REST object 资源进行持久化存储,本文介绍如何配置生成自签 https 证书,搭建 etcd 集群给 apiserver 使 ...

  10. WEB漏洞——RCE

    RCE(remote command/code execute)远程命令/代码执行漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统. RCE漏洞 应用程序有时需要调用一 ...