SOC-ESP32S3部分:17-I2C驱动实例-EEPROM温湿度传感器

article/2025/9/5 13:48:49

飞书文档https://x509p6c8to.feishu.cn/wiki/KrlCwmlKcikvZ5knxEbcrewwn1c

EEPROM

特别说明,目前ESP32S3由于IO数量少的原因,是没有连接底板的EEPROM的,我们这里只进行代码讲解,这个工程不能在板卡运行的。

我们学习基础课程时,知道底板上是有EEPROM的,就是BL24c02,这里我们不再重新讲解EEPROM的协议时序,如果你不清楚,可以回到51&STM32单片机课程进行了解,我们直接看实现。

原理图部分:

首先,EERPOM未连接到ESP32S3核心板卡,所以这里随便用一组IO进行说明

代码部分,驱动流程如下:

  1. 初始化I2C总线实例
  2. 创建I2C设备,添加到总线
  3. 往某个地址进行写入需要存储的数据
  4. 读取数据进行打印

需要注意的是:

EEPROM写入数据时,直接往某个地址进行写入即可,直接使用i2c_master_transmit。

EEPROM读取数据时,需要先写入需要读取数据的地址,然后再进行读取,使用先发送再读取函数i2c_master_transmit_receive。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gptimer.h"
#include "esp_log.h"#include <string.h>
#include "sdkconfig.h"
#include "driver/i2c_master.h"static const char *TAG = "EEPROM"; // 定义日志标签// I2C 引脚和设备配置
#define SCL_IO_PIN 4            // I2C 时钟线引脚编号
#define SDA_IO_PIN 5            // I2C 数据线引脚编号
#define DEVICE_ADDR 0xA0        // I2C 设备地址 (7-bit 地址)
#define MASTER_FREQUENCY 100000 // I2C 总线频率 (100kHz)
#define PORT_NUMBER -1          // I2C 端口号 (-1 表示使用默认端口)// 写入数据到 BL24C02
esp_err_t bl24c02_write(i2c_master_dev_handle_t dev_handle, uint16_t mem_addr, const uint8_t *data, size_t length)
{uint8_t buffer[1 + length];buffer[0] = (mem_addr) & 0xFF;    // 写入地址memcpy(buffer + 1, data, length); // 复制数据到缓冲区return i2c_master_transmit(dev_handle, buffer, sizeof(buffer) + length, pdMS_TO_TICKS(1000));
}// 从 BL24C02 读取数据
esp_err_t bl24c02_read(i2c_master_dev_handle_t dev_handle, uint16_t mem_addr, uint8_t *data, size_t length)
{uint8_t addr_buffer[1];addr_buffer[0] = (mem_addr) & 0xFF; // 高字节地址return i2c_master_transmit_receive(dev_handle, addr_buffer, sizeof(addr_buffer), data, length, pdMS_TO_TICKS(1000));
}void app_main(void)
{// 配置 I2C 总线参数i2c_master_bus_config_t i2c_bus_config = {.clk_source = I2C_CLK_SRC_DEFAULT, // 使用默认时钟源.i2c_port = PORT_NUMBER,           // 指定 I2C 端口.scl_io_num = SCL_IO_PIN,          // SCL 引脚编号.sda_io_num = SDA_IO_PIN,          // SDA 引脚编号.glitch_ignore_cnt = 7,            // 忽略毛刺计数};// 创建 I2C 总线句柄i2c_master_bus_handle_t bus_handle;ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle)); // 初始化 I2C 总线// 配置 I2C 设备参数i2c_device_config_t dev_cfg = {.dev_addr_length = I2C_ADDR_BIT_LEN_7, // 设备地址长度为 7 位.device_address = DEVICE_ADDR,         // 设备地址.scl_speed_hz = MASTER_FREQUENCY,      // SCL 时钟频率};// 创建 I2C 设备句柄i2c_master_dev_handle_t dev_handle;ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); // 添加设备到总线// 探测设备esp_err_t ret = i2c_master_probe(bus_handle, DEVICE_ADDR, 1000);if (ret == ESP_OK){ESP_LOGI(TAG, "Device at address 0x%02X found and responsive", DEVICE_ADDR);}else{ESP_LOGE(TAG, "Failed to find device at address 0x%02X", DEVICE_ADDR);}// 写入数据到 BL24C02uint8_t write_data[] = {0xAA, 0xBB, 0xCC, 0xDD};uint8_t mem_addr = 0x00; // 写入起始地址bl24c02_write(dev_handle, mem_addr, write_data, sizeof(write_data));//延时10ms 等待EEPROM写入完成vTaskDelay(pdMS_TO_TICKS(10));// 读取数据从 BL24C02uint8_t read_data[sizeof(write_data)];ret = bl24c02_read(dev_handle, mem_addr, read_data, sizeof(read_data));if (ret == ESP_OK){ESP_LOGI(TAG, "Data read successfully: ");for (int i = 0; i < sizeof(read_data); i++){printf("0x%02X ", read_data[i]);}printf("\n");}else{ESP_LOGE(TAG, "Failed to read data: %d", ret);}ESP_ERROR_CHECK(i2c_master_bus_rm_device(dev_handle));ESP_ERROR_CHECK(i2c_del_master_bus(bus_handle));ESP_LOGI(TAG, "I2C de-initialized successfully");while (1){vTaskDelay(pdMS_TO_TICKS(1000));}}

GXHT3L

温湿度传感器部分也是一样,先查看温湿度传感器连接到ESP32S3核心板的IO

温湿度传感器协议时序,可以查看51/STM32基础课程,驱动的流程如下

  1. 初始化I2C总线实例
  2. 创建I2C设备,添加到总线
  3. 初始化温湿度传感器,设置采样参数
  4. 轮询间隔读取温湿度数据,进行校验&打印
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gptimer.h"
#include "esp_log.h"#include <string.h>
#include "sdkconfig.h"
#include "driver/i2c_master.h"static const char *TAG = "GXHT3L"; // 定义日志标签// I2C 引脚和设备配置
#define SCL_IO_PIN 8               // I2C 时钟线引脚编号
#define SDA_IO_PIN 4               // I2C 数据线引脚编号
#define DEVICE_ADDR 0x44        // I2C 设备地址 (7-bit 地址)
#define MASTER_FREQUENCY 100000 // I2C 总线频率 (100kHz)
#define PORT_NUMBER -1          // I2C 端口号 (-1 表示使用默认端口)typedef enum
{/* 软件复位命令 */SOFT_RESET_CMD = 0x30A2,   /* 加热使能/禁能命令 */PREHEAT_ENABLE_CMD = 0x306D,PREHEAT_DISENABLE_CMD = 0x3066,/* 芯片状态命令 */DEVICE_STATUS_CMD = 0xF32D,/*单次测量模式命名格式:Repeatability_CS_CMDCS:Clock stretching*/HIGH_ENABLED_CMD    = 0x2C06,MEDIUM_ENABLED_CMD  = 0x2C0D,LOW_ENABLED_CMD     = 0x2C10,HIGH_DISABLED_CMD   = 0x2400,MEDIUM_DISABLED_CMD = 0x240B,LOW_DISABLED_CMD    = 0x2416,/*周期测量模式命名格式:Repeatability_MPS_CMDMPS:measurement per second*/HIGH_0_5_CMD   = 0x2032,MEDIUM_0_5_CMD = 0x2024,LOW_0_5_CMD    = 0x202F,HIGH_1_CMD     = 0x2130,MEDIUM_1_CMD   = 0x2126,LOW_1_CMD      = 0x212D,HIGH_2_CMD     = 0x2236,MEDIUM_2_CMD   = 0x2220,LOW_2_CMD      = 0x222B,HIGH_4_CMD     = 0x2334,MEDIUM_4_CMD   = 0x2322,LOW_4_CMD      = 0x2329,HIGH_10_CMD    = 0x2737,MEDIUM_10_CMD  = 0x2721,LOW_10_CMD     = 0x272A,/* 周期测量模式读取数据命令 */READOUT_FOR_PERIODIC_MODE = 0xE000,
} GXHT3L_CMD;static esp_err_t gxht3l_send_cmd(i2c_master_dev_handle_t dev_handle,GXHT3L_CMD cmd)
{uint8_t cmd_buffer[2];cmd_buffer[0] = cmd >> 8;cmd_buffer[1] = cmd;return i2c_master_transmit(dev_handle, cmd_buffer, sizeof(cmd_buffer), pdMS_TO_TICKS(1000));
}static void gxht3l_reset(i2c_master_dev_handle_t dev_handle)
{gxht3l_send_cmd(dev_handle,SOFT_RESET_CMD);
}static void gxht3l_init(i2c_master_dev_handle_t dev_handle){gxht3l_send_cmd(dev_handle,MEDIUM_2_CMD);
}static esp_err_t gxht3l_read_data(i2c_master_dev_handle_t dev_handle,uint8_t *data, size_t length)
{gxht3l_send_cmd(dev_handle,READOUT_FOR_PERIODIC_MODE);return i2c_master_receive(dev_handle, data, length, pdMS_TO_TICKS(1000));
}static uint8_t gxht3l_data_to_float(uint8_t* const data, float* temperature, float* humidity)
{uint16_t recv_temperature = 0;uint16_t recv_humidity = 0;/* 校验温度数据和湿度数据是否接收正确 */// if(CheckCrc8(data, 0xFF) != data[2] || CheckCrc8(&data[3], 0xFF) != data[5])//     return 1;/* 转换温度数据 */recv_temperature = ((uint16_t)data[0]<<8)|data[1];*temperature = -45 + 175*((float)recv_temperature/65535);/* 转换湿度数据 */recv_humidity = ((uint16_t)data[3]<<8)|data[4];*humidity = 100 * ((float)recv_humidity / 65535);return 0;
}void app_main(void)
{// 配置 I2C 总线参数i2c_master_bus_config_t i2c_bus_config = {.clk_source = I2C_CLK_SRC_DEFAULT, // 使用默认时钟源.i2c_port = PORT_NUMBER,           // 指定 I2C 端口.scl_io_num = SCL_IO_PIN,          // SCL 引脚编号.sda_io_num = SDA_IO_PIN,          // SDA 引脚编号.glitch_ignore_cnt = 7,            // 忽略毛刺计数};// 创建 I2C 总线句柄i2c_master_bus_handle_t bus_handle;ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle)); // 初始化 I2C 总线// 配置 I2C 设备参数i2c_device_config_t dev_cfg = {.dev_addr_length = I2C_ADDR_BIT_LEN_7, // 设备地址长度为 7 位.device_address = DEVICE_ADDR,         // 设备地址.scl_speed_hz = MASTER_FREQUENCY,      // SCL 时钟频率};// 创建 I2C 设备句柄i2c_master_dev_handle_t dev_handle;ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); // 添加设备到总线// 探测设备esp_err_t ret = i2c_master_probe(bus_handle, DEVICE_ADDR, 1000);if (ret == ESP_OK){ESP_LOGI(TAG, "Device at address 0x%02X found and responsive", DEVICE_ADDR);}else{ESP_LOGE(TAG, "Failed to find device at address 0x%02X", DEVICE_ADDR);}gxht3l_init(dev_handle);uint8_t recv_data[6] = {0};float temperature = 0.0;float humidity = 0.0;while (1){vTaskDelay(pdMS_TO_TICKS(2000));gxht3l_read_data(dev_handle,recv_data, sizeof(recv_data));if(gxht3l_data_to_float(recv_data, &temperature, &humidity)==0){ESP_LOGI(TAG,"temperature = %f, humidity = %f\n", temperature, humidity);}}}

http://www.hkcw.cn/article/HJKZAFPpSy.shtml

相关文章

局域网内文件共享的实用软件推荐

软件介绍 在日常办公、学习或家庭网络环境里&#xff0c;局域网内文件共享是个常见需求。有一款免费的局域网共享软件非常适合这种场景。 这款局域网共享软件使用起来非常简单&#xff0c;不需要安装&#xff0c;直接点击就能使用。 软件下载 链接&#xff1a;​​https://p…

华为OD机试真题——AI面板识别(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

EasyRTC音视频实时通话助力微信小程序:打造低延迟、高可靠的VoIP端到端呼叫解决方案

一、方案概述​ 在数字化通信浪潮下&#xff0c;端到端实时音视频能力成为刚需。依托庞大用户生态的微信小程序&#xff0c;是实现此类功能的优质载体。基于WebRTC的EasyRTC音视频SDK&#xff0c;为小程序VoIP呼叫提供轻量化解决方案&#xff0c;通过技术优化实现低延迟通信&a…

YOLOv8 实战指南:如何实现视频区域内的目标统计与计数

文章目录 YOLOv8改进 | 进阶实战篇&#xff1a;利用YOLOv8进行视频划定区域目标统计计数1. 引言2. YOLOv8基础回顾2.1 YOLOv8架构概述2.2 YOLOv8的安装与基本使用 3. 视频划定区域目标统计的实现3.1 核心思路3.2 完整实现代码 4. 代码深度解析4.1 关键组件分析4.2 性能优化技巧…

远程调用 | OpenFeign+LoadBalanced的使用

目录 RestTemplate 注入 OpenFeign 服务 LoadBalanced 服务 LoadBalanced 注解 RestTemplate 注入 创建 配置类&#xff0c;这里配置后 就不用再重新new一个了&#xff0c;而是直接调用即可 import org.springframework.cloud.client.loadbalancer.LoadBalanced; import …

Ansys Zemax | 手机镜头设计 - 第 2 部分:光机械封装

本文该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;涵盖了从概念、设计到制造和结构变形的分析。本文是四部分系列的第二部分&#xff0c;介绍了在 Ansys Speos 环境中编辑光学元件以及在整合机械组件后分析系统。案例研究对象是一家全球运营制造商的智能手机镜头系统…

ubuntu 22.04安装k8s高可用集群

文章目录 1.环境准备&#xff08;所有节点&#xff09;1.1 关闭无用服务1.2 环境和网络1.3 apt源1.4 系统优化1.5 安装nfs客户端 2. 装containerd&#xff08;所有节点&#xff09;3. master的高可用方案&#xff08;master上操作&#xff09;3.1 安装以及配置haproxy&#xff…

k8s中kubeSphere的安装使用+阿里云私有镜像仓库配置完整步骤

一、实验目的 1、掌握kubeSphere 的安装部署 2、掌握kubesphere 使用外部镜像仓库&#xff1b; 2、熟悉图像化部署任务&#xff1a;产生pod---定义服务--验证访问 本次实验旨在通过 KubeSphere 平台部署基于自定义镜像&#xff08;nginx:1.26.0 &#xff09;的有状态副本集…

innovus: write_lef_abstract如何写入stripe信息

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 block level需要把pg 信息写到lef里&#xff0c;方便top level查看&#xff0c;这里提供一种简单方法: write_lef_abstract -5.8 -PGPinLayers {ME5 ME6 ME7 ME8 AL_RDL} -str…

MySQL索引与事物

目录 一&#xff1a;MySQL索引介绍 1.索引概述 2.索引作用 3.索引的分类 关键区别 &#xff08;1&#xff09;普通索引 &#xff08;2&#xff09;唯一索引 &#xff08;3&#xff09;主键索引 &#xff08;4&#xff09;组合索引&#xff08;最左前缀) 4.全文索引&am…

光年号,国外云手机号的创新应用与发展趋势

光年号&#xff0c;国外云手机号的创新应用与发展趋势 光年号作为新兴通信技术代表&#xff0c;与国外云手机号结合&#xff0c;推动通信变革。光年号的灵活性提升了国外云手机号的使用效率&#xff0c;光年号服务正在全球扩展&#xff0c;光年号和国外云手机号的融合创新&…

Java开发经验——阿里巴巴编码规范实践解析7

摘要 本文主要解析了阿里巴巴 Java 开发中的 SQL 编码规范&#xff0c;涉及 SQL 查询优化、索引建立、字符集选择、分页查询处理、外键与存储过程的使用等多个方面&#xff0c;旨在帮助开发者提高代码质量和数据库操作性能&#xff0c;避免常见错误和性能陷阱。 1. 【强制】业…

【经验】Ubuntu中设置terminator的滚动行数、从Virtualbox复制到Windows时每行后多一空行

1、设置terminator的滚动行数 1.1 问题描述 在终端 terminator 中&#xff0c;调试程序时&#xff0c;只能查看有限行数的打印日志&#xff0c;大约是500行&#xff0c;怎么能增加行数 1.2 解决方法 1&#xff09;安装terminator sudo apt install terminator和 terminato…

Photoshop2025(PS2025)软件及安装教程

在数字图像编辑领域&#xff0c;Adobe Photoshop 一直是无可争议的王者。如今&#xff0c;Photoshop 2025 重磅登场&#xff0c;再次为我们带来了惊喜与变革&#xff0c;进一步巩固了它在行业中的领先地位。 Photoshop 2025 在人工智能方面的升级令人瞩目。其全新的 “Magic Se…

NHANES指标推荐:UAR

文章题目&#xff1a;The Uric Acid to Albumin Ratio Predicts All-cause and Cardiovascular Mortality Among U.S. Adults Results from the National Health and Nutrition Examination Survey in 2003-2018 中文标题&#xff1a;尿酸与白蛋白比值可预测美国成年人的全因死…

C++23 std::fstreams基础回顾

文章目录 引言1.1 std::fstreams概述1.2 std::fstreams的主要功能和常用操作 2. 独占模式 (P2467R1) 的详细介绍2.1 独占模式的定义和背景2.2 独占模式的作用和优势 3. C23 std::fstreams支持独占模式 (P2467R1) 的具体实现方式3.1 代码示例3.2 实现步骤解释 4. 使用该特性可能…

Unity3D仿星露谷物语开发55之保存游戏到文件

1、目标 将游戏保存到文件&#xff0c;并从文件中加载游戏。 Player在游戏中种植的Crop&#xff0c;我们希望保存到文件中&#xff0c;当游戏重新加载时Crop的GridProperty数据仍然存在。这次主要实现保存地面属性&#xff08;GridProperties&#xff09;信息。 我们要做的是…

Windows 中禁止在桌面放置文件以保持桌面整洁

假设用户名为xxx&#xff0c;进入文件夹C:\Users\xxx&#xff0c;选中该文件夹下桌面文件夹并单击右键选择属性。 点击编辑。 选中用户xxx并将其写入权限设置为拒绝。随后桌面在无法主动授权情况下无法新建文件或者文件夹&#xff08;设置权限之前可以先将桌面文件移动到别处&…

STM32开发全解析:从环境搭建到项目实战的技术文档撰写指南

在嵌入式开发领域&#xff0c;STM32系列微控制器凭借高性能、低功耗及丰富外设等特性&#xff0c;成为工程师的首选平台。本文以STM32F103C8T6为例&#xff0c;结合技术文档撰写规范&#xff0c;系统拆解从基础知识、开发环境到实战项目的全流程&#xff0c;为STM32技术传播提供…

AI数字人系统开发——引领未来交互革命

随着人工智能技术的不断发展&#xff0c;AI数字人系统开发正引领着一场前所未有的交互革命。它将打破传统的人机交互方式&#xff0c;为我们带来更加自然、智能、高效的交互体验。 我们的AI数字人系统开发&#xff0c;融合了多种先进的技术&#xff0c;如计算机视觉、语音识别…