HAL库STM32内部EEPROM保存结构体

本文介绍了如何利用STM32内部Flash作为EEPROM的替代方案,详细阐述了STM32的存储器映射、结构体定义、初始化、读写操作函数的编写,并提醒了程序下载时可能的数据擦除问题以及如何查看和调整程序占用空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、首先说一下初衷,有些程序的配置信息等需要永久保存,比如密码,用户配置,断电后不丢失,一般情况都会选择外部挂个E2PROM器件,常见的就是24C02了,单是STM32内部的程序存储器也是可以掉电保存的,不像外挂存储器的就可以用内部没有用到的FLASH来保存这些配置信息。虽然省了外挂器件节省了PCB空间和成本,但是也有缺点,读写次数或者刷程序时意外擦除,不能按字节操作等,有大神测试过速度,次数等并不是很逊色。根据情况自己选择吧。

2、根据数据手册,STM32系列将4G内存空间进行存储器映射,其中地址0x0800 000为内部主存储区首地址,也就是常说的内部Flash首地址,根据型号不同Flash内存大小不同, 

在此以C8T6为例举例,其他的可以查看数据手册存储器映射部分C8为中容量产品,64K的Flash,也就是ROM内存地址为0x0800 0000-0X0801 0000共64K,按1K划分页,Flash不像24C02这种器件可以按字节操作,STM32的内部FLASH只能按页操作,而且必须先整页擦除为0xFF,然后再写入,可以按半字,字,双字写入

 从Kei可以看出内部Flash起始地址和大小为0X10000也就是64kByte,还有运行内存RAM也就是起始地址0X2000 0000大小为0X5000(20KB)

再贴一个CubeMX的截图

 3、介绍完接下来开始按操作步骤写程序,先定义一个结构体,建议按照变量占用内存空间大小,从小到大顺序定义因为牵扯到内存对齐问题,可能会占用更大空间,我这里是按照人类更容易理解顺序定义的占用空间略大。#pragmatic pack(1) 可以修改字节对齐数量为1,比较省空间,慎用可能会产生别的问题

typedef struct 
{
uint16_t temperature_set;							//温度设定值
uint8_t rest_time;										//休眠时间
uint8_t sleep_time;										//睡眠时间
uint8_t OLED_Brightness;							/OLED的显示亮度
uint8_t POWER_calibration_point[3];		//电源电压校准点 1 2 3
uint16_t POWER_calibration[3];				//电源电压校准值1 2 3
uint16_t T12_calibration_point[9];		//电源电压校准点1-9
uint16_t T12_calibration[9];					//温度转换的校准值100 150 200 250 300 350 400 450 500
}system_set_struct;

 再进行初始化

system_set.OLED_Brightness=200;
system_set.rest_time=2;
system_set.sleep_time=5;
system_set.temperature_set=300;

 这里我将64K就是64页起始地址都宏定义了,你们可以不用这么麻烦

/* Base address of the Flash sectors STM32F103C8 64KB ROM 0x08000000-0x08010000*/ 
#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base add
### 使用STM32 HAL与外部EEPROM实现安全的密码存储 为了在STM32平台上使用HAL与外部EEPROM(如AT24C02)实现安全的密码存储,需考虑几个方面:硬件连接、初始化配置、读写函数设计以及安全性措施。 #### 硬件连接 确保STM32通过I2C总线正确连接至外部EEPROM芯片。通常情况下,SCL和SDA引脚分别对应于I2C时钟线和数据线,并应设置合适的上下拉电阻以保障信号质量[^2]。 #### 初始化配置 在程序启动阶段完成必要的初始化工作,包括但不限于: - 配置GPIO端口为复用功能模式以便支持I2C通信; - 调用`MX_I2C1_Init()`等API来设定I2C外设参数,比如波特率、地址格式等; - 创建指向I2C_HandleTypeDef结构体实例的指针变量用于后续调用; ```c // I2C初始化函数声明 void MX_I2C1_Init(void); ``` #### 密码加密处理 考虑到安全性,在实际应用中不应直接保存明文形式的密码。建议采用哈希算法(如SHA-256),先对原始输入做散列转换后再存入EEPROM内。这样即使有人获取到了物理访问权限也无法轻易破解真实值[^4]。 #### 数据读写流程 编写专门针对特定位置执行单字节或多字节数组传输的功能模块。下面给出一段简化版的例子展示如何向指定地址处写入经过编码后的字符串型态的数据片段: ```c #include "main.h" #define EEPROM_ADDRESS 0xA0 // AT24C02设备地址 #define PASSWORD_HASH_LENGTH 32 // 假定hash长度为32字节 /** * @brief 向EEPROM指定位置写入一定数量的字节 */ static void eeprom_write_bytes(uint16_t mem_addr, uint8_t* data_ptr, int length){ /* 构造发送缓冲区 */ uint8_t tx_buffer[length + 2]; tx_buffer[0] = (uint8_t)(mem_addr >> 8); // 地址高八位 tx_buffer[1] = (uint8_t)(mem_addr & 0xFF); // 地址低八位 memcpy(&tx_buffer[2], data_ptr, length); /* 发送命令给从机*/ HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, tx_buffer, length+2, HAL_MAX_DELAY); } /* ... */ char password_hash[PASSWORD_HASH_LENGTH]; // 存储计算得到的hash结果 eeprom_write_bytes(STARTING_MEMORY_LOCATION, (uint8_t*)password_hash, PASSWORD_HASH_LENGTH); ``` 对于验证过程,则是从相同的位置读回相应大小的信息块并与当前用户提交的内容对比其一致性即可判断是否匹配成功。 #### 安全性考量 除了上述提到的方法之外,还可以采取更多策略增强系统的整体防护能力,例如限定每次尝试次数防止暴力攻击、定期更换密钥提高抗分析难度等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_43175613

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值