STM32MX配置EEPROM(AT24C02)------保姆级教程
————————————————————————————————————
⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。
⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动,包括ADC、UART、RS485、EEPROM(IIC)、FLASH(SPI)等等。
⏩本篇文章对STM32CUBEMX配置RRPROM(AT24C02)做一个详细的使用教程。
⏩感谢你的阅读,不对的地方欢迎指正。
————————————————————————————————————
EEPROM
- AT24C02工作原理
- 实验环境
- MX配置
- 驱动代码
- 测试结果
AT24C02工作原理
引脚封装

SCL 串行时钟
AT24C02串行时钟输入管脚用于产生器件所有数据发送或接收的时钟,这是一个输入管脚。
SDA 串行数据/地址
AT24C02 双向串行数据/地址管脚用于器件所有数据的发送或接收,SDA 是一个开漏输出管脚,可与其它开漏输出或集电极开路输出进行线或(wire-OR)。
A0、A1、A2 器件地址输入端
这些输入脚用于多个器件级联时设置器件地址,当这些脚悬空时默认值为0。当使用AT24C02 时最大可级联8个器件。如果只有一个AT24C02被总线寻址,这三个地址输入脚(A0、A1、A2 )可悬空或连接到Vss or GND。
WP 写保护
如果WP管脚连接到Vcc,所有的内容都被写保护只能读。当WP管脚连接到Vss or GND 或悬空允许器件进行正常的读/写操作。
具体原理可以参考
AT24C02芯片使用介绍
实验环境
- USB转串口
- AT24C02
- STM32H723ZGT6开发板
硬件连接:

我这里接的是PB8和PB9
MX配置
板子、时钟、调试之类的配置就不说了,具体可以看看这篇:
STM32CUBEMX配置ADC(多通道轮询)(STM32H7)–保姆级教程
这里只说一下IIC的具体配置
根据你的连接自己配置

我的引脚是PB8,PB9

驱动代码
at24C02.h
我使用两个共用体去存储浮点型和整形的数据,这是最简单的方法。
#ifndef AT24C02_H_
#define AT24C02_H_#include "stm32H7xx_hal.h" //HAL库文件声明#define AT24C02_ADDR_WRITE 0xA0 // 写命令
#define AT24C02_ADDR_READ 0xA1 // 读命令#define ADDR_24LCxx_Write 0xA0 //AT24C02写地址
#define ADDR_24LCxx_Read 0xA1 //AT24C02读地址
#define BufferSize 256 //读写缓冲区大小union float_union{float float_write_dat; // 浮点数占4个字节double double_write_dat; // 双精度浮点数占8个字节uint8_t buf[8]; // 定义 8个字节 的空间
};
union int_union{int int_dat; //整型数占四个字节uint8_t buf[4]; //定义4个字节的空间
};uint8_t At24c02_Write_Byte(uint16_t addr, uint8_t* dat); //AT24C02任意地址写一个字节数据
uint8_t At24c02_Read_Byte(uint16_t addr, uint8_t* read_buf);//AT24C02任意地址读一个字节数据
uint8_t At24c02_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size);// AT24C02任意地址连续写多个字节数据
uint8_t At24c02_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size);//AT24C02任意地址连续读多个字节数据
#endif
at24c02.c
#include "at24c02.h"
#include "i2c.h"
/*** @brief AT24C02任意地址写一个字节数据* @param addr —— 写数据的地址(0-255)* @param dat —— 存放写入数据的地址* @retval 成功 —— HAL_OK
*/
uint8_t At24c02_Write_Byte(uint16_t addr, uint8_t* dat)
{HAL_StatusTypeDef result;result = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, 1, 0xFFFF);HAL_Delay(5); // 写一个字节,延迟一段时间,不能连续写return result;
}/*** @brief AT24C02任意地址读一个字节数据* @param addr —— 读数据的地址(0-255)* @param read_buf —— 存放读取数据的地址* @retval 成功 —— HAL_OK
*/
uint8_t At24c02_Read_Byte(uint16_t addr, uint8_t* read_buf)
{return HAL_I2C_Mem_Read(&hi2c1, AT24C02_ADDR_READ, addr, I2C_MEMADD_SIZE_8BIT, read_buf, 1, 0xFFFF);
}/*** @brief AT24C02任意地址连续写多个字节数据* @param addr —— 写数据的地址(0-255)* @param dat —— 存放写入数据的地址* @retval 成功 —— HAL_OK
*/
uint8_t At24c02_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size)
{uint8_t i = 0;uint16_t cnt = 0; // 写入字节计数HAL_StatusTypeDef result; // 返回是否写入成功/* 对于起始地址,有两种情况,分别判断 */if(0 == addr % 8){/* 起始地址刚好是页开始地址 *//* 对于写入的字节数,有两种情况,分别判断 */if(size <= 8){// 写入的字节数不大于一页,直接写入result = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, size, 0xFFFF);HAL_Delay(20); // 写完八个字节(最多八个字节),延迟久一点return result;}else{// 写入的字节数大于一页,先将整页循环写入for(i = 0; i < size/8; i++){HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], 8, 0xFFFF);// 一次写入了八个字节,延迟久一点HAL_Delay(20); // 写完八个字节,延迟久一点addr += 8;cnt += 8;}// 将剩余的字节写入result = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], size - cnt, 0xFFFF);HAL_Delay(20); // 写完八个字节(最多八个字节),延迟久一点return result;}}else{/* 起始地址偏离页开始地址 *//* 对于写入的字节数,有两种情况,分别判断 */if(size <= (8 - addr%8)){/* 在该页可以写完 */result = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, size, 0xFFFF);HAL_Delay(20); // 写完八个字节(最多八个字节),延迟久一点return result;}else{/* 该页写不完 */// 先将该页写完cnt += 8 - addr%8;HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, cnt, 0xFFFF);HAL_Delay(20); // 写完八个字节(最多八个字节),延迟久一点addr += cnt;// 循环写整页数据for(i = 0;i < (size - cnt)/8; i++){HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], 8, 0xFFFF);HAL_Delay(20); // 写完八个字节,延迟久一点addr += 8;cnt += 8;}// 将剩下的字节写入result = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], size - cnt, 0xFFFF);HAL_Delay(20); // 写完八个字节(最多八个字节),延迟久一点return result;} }
}/*** @brief AT24C02任意地址连续读多个字节数据* @param addr —— 读数据的地址(0-255)* @param dat —— 存放读出数据的地址* @retval 成功 —— HAL_OK
*/
uint8_t At24c02_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size)
{return HAL_I2C_Mem_Read(&hi2c1, AT24C02_ADDR_READ, addr, I2C_MEMADD_SIZE_8BIT, recv_buf, size, 0xFFFF);
}
main.c
//AT24C02
uint8_t WriteBuffer[BufferSize] = {0};//AT24C02写缓冲区
uint8_t ReadBuffer[BufferSize] = {0}; //AT24C02读缓冲区//测试// 单个字节 读写测试uint8_t simple_write_dat = 0xa5; // 一个字节uint8_t simple_recv_buf = 0;if(HAL_OK == At24c02_Write_Byte(10, &simple_write_dat)){printf("Simple data write success \r\n");} else {printf("Simple data write fail \r\n");}HAL_Delay(50); // 写一次和读一次之间需要短暂的延时if(HAL_OK == At24c02_Read_Byte(10, &simple_recv_buf)){printf("Simple data read success, recv_buf = 0x%02X \r\n", simple_recv_buf);} else {printf("Simple data read fail \r\n");}printf("--------------------- \r\n");// 单个字节读写 测试结束// 浮点数 读写测试union float_union send_float_data; // 用来发送union float_union rev_float_data; // 用来接收union int_union send_int_data; //发送union int_union rev_int_data; //接收// 先测试第一个 浮点数send_float_data.float_write_dat = 3.1415f;if(HAL_OK == At24c02_Write_Amount_Byte(20, send_float_data.buf, 4)){printf("Float data write success \r\n");} else {printf("Float data write fail \r\n");}HAL_Delay(50);if(HAL_OK == At24c02_Read_Amount_Byte(20, rev_float_data.buf, 4)){// 默认输出六位小数printf("Float data read success, recv_buf = %f \r\n", rev_float_data.float_write_dat);} else {printf("Float data read fail \r\n");}// 测试第二个 双精度浮点数send_float_data.double_write_dat = 3.1415f;if(HAL_OK == At24c02_Write_Amount_Byte(20, send_float_data.buf, 8)){printf("Double data write success \r\n");} else {printf("Double data write fail \r\n");}HAL_Delay(50);if(HAL_OK == At24c02_Read_Amount_Byte(20, rev_float_data.buf, 8)){// 最多15位小数printf("Double data read success, recv_buf = %.15f \r\n", rev_float_data.double_write_dat);} else {printf("Double data read fail \r\n");}printf("--------------------- \r\n");// 浮点数读写测试 测试结束// 测试第三个 整形数send_int_data.int_dat = 2147483647;if(HAL_OK == At24c02_Write_Amount_Byte(30,send_int_data.buf, 4)){printf("int data write success \r\n");} else {printf("int data write fail \r\n");}HAL_Delay(50);if(HAL_OK == At24c02_Read_Amount_Byte(30, rev_int_data.buf, 4)){printf("int data read success, recv_buf = %d \r\n", rev_int_data.int_dat);} else {printf("int data read fail \r\n");}printf("--------------------- \r\n");// 整型数读写测试 测试结束// 连续数据读写测试uint8_t write_dat[22] = {0}; // 22个字节uint8_t recv_buf[22] = {0};printf("正在往数组中填充数据... \r\n");for(int i = 0; i < 22; i++){write_dat[i] = i;printf("%02X ", write_dat[i]);}printf("\r\n 数组中数据填充完毕... \r\n");if(HAL_OK == At24c02_Write_Amount_Byte(0, write_dat, 22)){printf("24c02 write success \r\n");} else {printf("24c02 write fail \r\n");}HAL_Delay(50); // 写一次和读一次之间需要短暂的延时if(HAL_OK == At24c02_Read_Amount_Byte(0, recv_buf, 22)){printf("read success \r\n");for(int i = 0; i < 22; i++) {printf("0x%02X ", recv_buf[i]);}} else {printf("read fail\r\n");}// 连续数据读写 测试结束
测试结果

可以看到存取单个字节、多个字节、浮点数、双精度浮点数、整型数都没有问题。
相关文章:
STM32MX配置EEPROM(AT24C02)------保姆级教程
———————————————————————————————————— ⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动&#x…...
微信小程序 样式和全局配置
WXSS wxss 把屏幕分为750个物理像素,大屏大,小屏小,随着设备不一致自动适配 推荐使用iPhone6作为标准,1个rpx 0.5个px,把px乘以2就是rpx的参数 import 导入外部样式表 import /common/common.wxss 样式 权重一…...
一.初识C语言
一.初识C语言 C语言标准规定: sizeof(long)>sizeof(int)就可以了变量要定义在当前代码块的最前面 #defin _CRT_SECURE_NO_WARNINGS 1#include <stdio.h> //包含一个stdio.h的文件 std-标准standard input outputint main() //主函数-程序的入口-main函数…...
filebeat到kafka示例
docker run -d \ --namefilebeat_7.14_0 \ #filebeat名称 --userroot \ --volume"/data/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml" \ #映射filebeat.yml配置 --volume"/data/filebeat/log:/usr/share/filebeat/log" \…...
AlmaLinux系统下的Zabbix汉化
我安装的是zabbix下的虚拟机,安装完成后,直接可以打开网站了,但是界面是英文,看了设置,没有中文选项,就需要在系统中安装中文字符集了。 # locale -a #查看里面没有zh_CN之类的项 # dnf install -…...
【网络编程】(TCP流套接字编程 ServerSocket API Socket API 手写TCP版本的回显服务器 TCP中的长短连接)
文章目录 网络编程TCP流套接字编程ServerSocket APISocket APITCP中的长短连接手写TCP版本的回显服务器 网络编程 TCP流套接字编程 TCP提供的API主要是两个类:ServerSocket 和 Socket . TCP不需要一个类来表示"TCP数据报"因为TCP不是以数据报为单位进行传输的.是以…...
企业级PaaS低代码快开平台源码,基于 Salesforce Platform 的开源替代方案
PaaS低代码快开平台是一种快速开发应用系统的工具,用户通过少量代码甚至不写代码就可以快速构建出各种应用系统。 随着信息化技术的发展,企业对信息化开发的需求正在逐渐改变,传统的定制开发已经无法满足企业需求。低代码开发平台࿰…...
【LeetCode】72.编辑距离
题目 给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符 示例 1: 输入:word1 "horse", word2 "…...
大模型,开源干不掉闭源
开源大模型对闭源大模型的冲击,变得非常猛烈。 今年3月,Meta发布了Llama(羊驼),很快成为AI社区内最强大的开源大模型,也是许多模型的基座模型。有人戏称,当前的大模型集群,就是一堆各…...
Redis 九种数据类型的基本操作
一、redis9种数据类型的基本操作 ①key操作 #查找所有的key 127.0.0.1:6379> keys * 1) "pop" 2) "mylist" 3) "lpl" 4) "myset" #设置key的过期时间 返回1表示执行成功,0表示失败,出现问题 127.0.0.1:6379…...
爬取微博热搜榜并进行数据分析
设计方案 爬虫爬取的内容 :爬取微博热搜榜数据。 网络爬虫设计方案概述 用requests库访问页面用get方法获取页面资源,登录页面对页面HTML进行分析,用beautifulsoup库获取并提取自己所需要的信息。再讲数据保存到CSV文件中,进行…...
基于深度神经网络的肺炎检测系统实现
一、说在前面 使用AI进行新冠肺炎图像诊断可以加快病例的诊断速度,提高诊断的准确性,并在大规模筛查中发挥重要作用,从而更好地控制和管理这一流行病。然而,需要强调的是,AI技术仅作为辅助手段,最终的诊断决…...
C# LINQ和Lambda表达式对照
C# LINQ和Lambda表达式对照 1. 基本查询语句 Linq语法: var datafrom a in db.Areas select a ; Lamda语法: var datadb.Areas; sql语法: SELECT * FROM Areas2. 简单的WHERE语句 Linq语法: var datafrom a in db.orderI…...
二、SQL-6.DCL-1).用户管理
一、DCL介绍 Data Control Language 数据控制语言 用来管理数据库 用户、控制数据库的 访问权限。 二、语法 1、管理用户 管理用户在系统数据库mysql中的user表中创建、删除一个用户,需要Host(主机名)和User(用户名࿰…...
ElasticSearch学习--数据聚合
介绍 数据聚合可以帮助我们对海量的数据进行统计分析,如果结合kibana,我们还能形成可视化的图形报表。自动补全可以根据用户输入的部分关键字去自动补全和提示。数据同步可以帮助我们解决es和mysql的数据一致性问题。集群可以帮助我们了解结构和不同节点…...
PostMan+Jmeter工具介绍及安装
目录 一、PostMan介绍编辑 二、下载安装 三、Postman与Jmeter的区别 一、开发语言区别: 二、使用范围区别: 三、使用区别: 四、Jmeter安装 附一个详细的Jmeter按照新手使用教程,感谢作者,亲测有效。 五、Jme…...
AutoSAR系列讲解(实践篇)7.4-实验:配置SWCRTE
注意: 实验篇是重点,有条件的同学最好跟着做一遍,然后回头对照着7.1-7.3理解其配置的目的和意义。实验下篇将在7.7节中继续做 一、实验概览 1、实验目的 通过本次实验,主要是让大家对Dev的配置有一个全流程的学习。这里会用到前两节的内容,将其串联起来,让大家能完整的…...
腾讯云内存型CVM服务器MA3、M6、M6ce和M5处理器CPU说明
腾讯云内存型CVM服务器CPU处理器大全,CVM内存型MA3、内存型M6、安全增强内存型M6ce、内存型M6p、内存型M5、MA2、M4、M3、M2、M1处理器主频、CPU性能性能大全说明,腾讯云内存型云服务器具有大内存的特点,适合高性能数据库、分布式内存缓存等需…...
集睿致远推出CS5466多功能拓展坞方案:支持DP1.4、HDMI2.1视频8K输出
ASL新推出的 CS5466是一款Type-C/DP1.4转HDMI2.1的显示协议转换芯片,,它通过类型C/显示端口链路接收视频和音 频流,并转换为支持TMDS或FRL输出信令。DP接收器支持81.Gbp s链路速率。HDMI输出端口可以作为TMDS或FRL发射机工作。FRL发射机符合HDMI 2.1规范…...
SQL中为何时常见到 where 1=1?
你是否曾在 SELECT 查询中看到过 WHERE 11 条件。我在许多不同的查询和许多 SQL 引擎中都有看过。这条件显然意味着 WHERE TRUE,所以它只是返回与没有 WHERE 子句时相同的查询结果。此外,由于查询优化器几乎肯定会删除它,因此对查询执行时间没…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
