当前位置: 首页 > news >正文

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

飞书文档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);}}}

相关文章:

  • Java开发经验——阿里巴巴编码规范实践解析6
  • Rust使用Cargo构建项目
  • 常见的分词算法
  • SAP BASIS常用事务代码ST06 操作系统监控
  • @ModelAttribute、@RequestBody、@RequestParam、@PathVariable 注解对比
  • VUE3+ts 实践记录
  • 【AI面试秘籍】| 第24期:Transformers / LLM的词表应该选多大?
  • 从本地到云端:Code App+SSH协议在iPad开发中的性能优化实战
  • pyinstaller 使用 控制台闪退解决办法
  • 文本预处理
  • ubuntu24.04与ubuntu22.04比,有什么新特性?
  • PS linux 基础篇1-AXI_DMA
  • 大数据学习(125)-hive数据分析
  • STM32CUBE打印浮点数据-cmake配置
  • NodeJS 基于 Koa, 开发一个读取文件,并返回给客户端文件下载,以及读取文件形成列表和文件删除的代码演示
  • 通配符(Wildcard)与正则表达式(Regular Expression)的关系及区别
  • MySQL高可用方案:Keepalived+双主库架构深度解析与实战指南
  • scrollTop 设为 0 不生效的可能原因
  • 23、Swift框架微调实战(3)-Qwen2.5-VL-7B LORA微调OCR数据集
  • 01.认识Kubernetes
  • 班级网站建设php/做网站公司哪家比较好
  • 河北做网站公司那家好/设计公司排名
  • 平阴县城乡建设委员会的网站/seo是什么意思seo是什么职位
  • 江苏网站建设公司/推广文章的注意事项
  • 无锡网站建设企业排名/seo快速排名的方法
  • 有哪些做设计交易网站有哪些内容/色盲测试