4. 基于 ESP-SR 的唤醒词识别基础测试
任务目标
在 ESP32-S3 上通过 I2C 总线连接 SHT30 温湿度传感器,读取温度与湿度数据,并通过串口打印。通过本案例掌握 I2C 通信协议的基本流程:初始化总线、设备寻址、寄存器读写、数据解析。
硬件与接线
- 开发板:ESP32-S3-DevKitC-1(或兼容板)
- 传感器:SHT30(I2C 地址
0x44,默认地址) - 接线:
SDA→ GPIO8,SCL→ GPIO9(ESP32-S3 默认 I2C 引脚,可自行修改) - 供电:传感器 VIN → 3.3V,GND → GND
实现原理
SHT30 通过 I2C 接口通信,读取数据需两步:先向传感器发送测量命令(0x2C 0x06 表示高重复性测量),等待约 15ms 后读取 6 字节数据(温度高字节、温度低字节、CRC、湿度高字节、湿度低字节、CRC)。温度与湿度均为 16 位无符号整数,按公式换算为实际物理量。
完整代码
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define I2C_MASTER_SCL_IO 9
#define I2C_MASTER_SDA_IO 8
#define I2C_MASTER_NUM 0
#define I2C_MASTER_FREQ_HZ 100000
#define SHT30_ADDR 0x44
#define SHT30_MEAS_CMD_HIGH 0x2C
#define SHT30_MEAS_CMD_HIGH_2ND 0x06
static const char *TAG = "sht30";
// 初始化 I2C 主机
static void i2c_master_init(void) {
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(I2C_MASTER_NUM, &conf);
i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0);
}
// 发送测量命令
static esp_err_t sht30_send_cmd(void) {
uint8_t cmd[2] = {SHT30_MEAS_CMD_HIGH, SHT30_MEAS_CMD_HIGH_2ND};
i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
i2c_master_start(cmd_handle);
i2c_master_write_byte(cmd_handle, (SHT30_ADDR << 1) | I2C_MASTER_WRITE, true);
i2c_master_write(cmd_handle, cmd, 2, true);
i2c_master_stop(cmd_handle);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd_handle, pdMS_TO_TICKS(100));
i2c_cmd_link_delete(cmd_handle);
return ret;
}
// 读取 6 字节数据
static esp_err_t sht30_read_data(uint8_t *buf, size_t len) {
i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
i2c_master_start(cmd_handle);
i2c_master_write_byte(cmd_handle, (SHT30_ADDR << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd_handle, buf, len, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd_handle);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd_handle, pdMS_TO_TICKS(100));
i2c_cmd_link_delete(cmd_handle);
return ret;
}
// 解析并打印温湿度
static void sht30_parse_and_print(uint8_t *data) {
uint16_t raw_temp = (data[0] << 8) | data[1];
uint16_t raw_humi = (data[3] << 8) | data[4];
float temp = -45.0f + 175.0f * (float)raw_temp / 65535.0f;
float humi = 100.0f * (float)raw_humi / 65535.0f;
ESP_LOGI(TAG, "Temperature: %.2f °C, Humidity: %.2f %%RH", temp, humi);
}
void app_main(void) {
i2c_master_init();
ESP_LOGI(TAG, "I2C initialized successfully");
uint8_t data[6];
while (1) {
if (sht30_send_cmd() == ESP_OK) {
vTaskDelay(pdMS_TO_TICKS(20)); // 等待测量完成
if (sht30_read_data(data, 6) == ESP_OK) {
sht30_parse_and_print(data);
} else {
ESP_LOGE(TAG, "Failed to read data");
}
} else {
ESP_LOGE(TAG, "Failed to send command");
}
vTaskDelay(pdMS_TO_TICKS(2000)); // 每 2 秒读取一次
}
}
编译与烧录
idf.py set-target esp32s3
idf.py menuconfig # 无需额外配置,默认引脚即可
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
验证方法
烧录并运行后,在串口监视器中观察输出。若接线正确且传感器工作正常,应每 2 秒打印一行温湿度数据,例如:
I (1234) sht30: Temperature: 25.36 °C, Humidity: 48.52 %RH
判定通过条件:
- 串口持续输出温湿度数据,无报错信息;
- 温度值在室温合理范围(约 15~35°C),湿度值在 20%~80%RH 范围;
- 用手捏住传感器或对其哈气,湿度值应明显上升,说明数据真实反映环境变化。
常见问题
- 读取失败或超时:检查 SDA/SCL 接线是否接反,确认传感器供电为 3.3V,并检查 I2C 地址是否为 0x44(部分模块地址为 0x45,可通过 ADDR 引脚修改)。
- 数据始终为 0 或固定值:多为传感器未正确响应,可尝试降低 I2C 频率至 50kHz,或检查上拉电阻是否连接。