news 2026/5/11 23:58:20

手把手教你用STM32F103的IIC接口读取SHT31温湿度数据(附完整工程)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用STM32F103的IIC接口读取SHT31温湿度数据(附完整工程)

从零构建STM32F103与SHT31的I2C通信系统:硬件连接、软件配置与数据解析全指南

在物联网和智能硬件快速发展的今天,环境监测已成为众多项目的核心需求。温湿度传感器作为最基础的环境感知元件,其稳定可靠的驱动实现是嵌入式开发者必须掌握的技能。本文将带领初学者使用STM32F103系列单片机,通过I2C接口与高精度SHT31温湿度传感器建立通信,从硬件连接到软件实现,逐步构建完整的测量系统。

1. 硬件准备与电路连接

1.1 所需材料清单

  • 主控芯片:STM32F103C8T6(正点原子Mini开发板)
  • 传感器模块:SHT31-DIS温湿度传感器
  • 连接线材:杜邦线若干(建议使用不同颜色区分信号)
  • 开发环境
    • Keil MDK-ARM或STM32CubeIDE
    • STM32CubeMX配置工具
    • 串口调试助手(如Putty、SecureCRT)

1.2 引脚连接详解

SHT31传感器与STM32的硬件连接需要特别注意电平匹配和信号完整性。以下是标准连接方式:

SHT31引脚STM32引脚功能说明
VCC3.3V电源正极
GNDGND电源地
SDAPC11I2C数据线
SCLPC12I2C时钟线

提示:实际项目中,当通信距离超过20cm时,建议在SDA和SCL线上各串联一个100Ω电阻,并添加2.2KΩ上拉电阻至3.3V,以提高信号质量。

1.3 硬件连接常见问题排查

初次连接时,开发者常会遇到以下问题:

  1. 通信失败

    • 检查电源电压是否稳定(3.3V±5%)
    • 确认SDA/SCL线序是否正确
    • 测量上拉电阻是否正常工作
  2. 数据不稳定

    • 确保电源去耦电容(0.1μF)靠近传感器VCC引脚
    • 检查杜邦线接触是否良好
    • 避免与高频信号线平行走线

2. 开发环境配置与工程建立

2.1 STM32CubeMX基础配置

使用STM32CubeMX可以快速生成初始化代码,大幅降低开发难度:

// 在CubeMX中进行如下配置: 1. 选择正确的STM32F103C8T6型号 2. 启用I2C1外设(或I2C2,根据实际连接) 3. 配置PC11为I2C_SDA,PC12为I2C_SCL 4. 设置I2C时钟速度为标准模式(100kHz) 5. 启用USART1用于调试输出(115200bps) 6. 生成Keil或IDE项目代码

2.2 关键外设初始化代码解析

生成的初始化代码中,需要特别关注以下几个部分:

// I2C初始化结构体示例 hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); }

2.3 工程目录结构规划

合理的项目结构能提高代码可维护性:

├── Core │ ├── Inc │ └── Src ├── Drivers │ ├── STM32F1xx_HAL_Driver │ └── CMSIS ├── SHT31 │ ├── sht31.h │ └── sht31.c └── Middlewares

3. SHT31驱动实现详解

3.1 传感器通信协议分析

SHT31采用标准I2C协议,但有几点特殊之处:

  • 设备地址:0x44(7位地址)
  • 测量命令
    • 高重复性测量:0x2C06
    • 中重复性测量:0x2C0D
    • 低重复性测量:0x2C10
  • 数据格式
    • 温度:16位原始数据,需按公式转换
    • 湿度:16位原始数据,需按公式转换

3.2 核心驱动函数实现

以下是完整的传感器驱动实现:

// sht31.h 头文件定义 #define SHT31_ADDR 0x44<<1 // 7位地址左移1位 typedef enum { SHT31_HIGH_REPEAT = 0x2C06, SHT31_MED_REPEAT = 0x2C0D, SHT31_LOW_REPEAT = 0x2C10 } SHT31_Repeatability; uint8_t SHT31_ReadTempHumid(float *temp, float *humid, SHT31_Repeatability rep);
// sht31.c 驱动实现 uint8_t SHT31_ReadTempHumid(float *temp, float *humid, SHT31_Repeatability rep) { uint8_t cmd[2]; uint8_t data[6]; // 发送测量命令 cmd[0] = rep >> 8; // 命令高字节 cmd[1] = rep & 0xFF; // 命令低字节 if(HAL_I2C_Master_Transmit(&hi2c1, SHT31_ADDR, cmd, 2, HAL_MAX_DELAY) != HAL_OK) return 0; // 等待测量完成(根据重复性等级不同等待时间不同) uint16_t delay_ms = rep == SHT31_HIGH_REPEAT ? 15 : (rep == SHT31_MED_REPEAT ? 6 : 4); HAL_Delay(delay_ms); // 读取测量结果 if(HAL_I2C_Master_Receive(&hi2c1, SHT31_ADDR|0x01, data, 6, HAL_MAX_DELAY) != HAL_OK) return 0; // 数据校验(CRC校验可在此添加) // 数据转换 uint16_t temp_raw = (data[0] << 8) | data[1]; uint16_t humid_raw = (data[3] << 8) | data[4]; *temp = -45 + 175 * ((float)temp_raw / 65535.0); *humid = 100 * ((float)humid_raw / 65535.0); return 1; }

3.3 数据转换与校验

SHT31提供的数据需要经过特定公式转换:

温度转换公式

T(°C) = -45 + 175 × (temp_raw / 65535)

湿度转换公式

RH(%) = 100 × (humid_raw / 65535)

注意:实际应用中应考虑添加CRC校验以提高数据可靠性,特别是环境干扰较大的场合。

4. 系统集成与性能优化

4.1 主程序逻辑实现

将驱动集成到主程序中,实现周期性测量:

// main.c #include "sht31.h" #include <stdio.h> float temperature, humidity; char msg[64]; int main(void) { HAL_Init(); SystemClock_Config(); MX_I2C1_Init(); MX_USART1_UART_Init(); while (1) { if(SHT31_ReadTempHumid(&temperature, &humidity, SHT31_HIGH_REPEAT)) { sprintf(msg, "Temperature: %.2f C, Humidity: %.2f %%\r\n", temperature, humidity); HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); } else { HAL_UART_Transmit(&huart1, (uint8_t*)"Read failed!\r\n", 13, HAL_MAX_DELAY); } HAL_Delay(1000); } }

4.2 通信可靠性增强措施

为提高I2C通信稳定性,可采取以下措施:

  1. 错误处理机制

    • 添加超时重试逻辑
    • 实现通信失败后的硬件复位
  2. 信号质量优化

    • 缩短通信线长度
    • 添加适当的终端匹配
    • 在PCB设计时保持I2C走线远离高频信号
  3. 软件滤波

    • 实现滑动平均滤波
    • 设置数据合理性检查

4.3 低功耗设计考虑

对于电池供电应用,可优化功耗:

  • 间歇工作模式

    // 设置传感器进入低功耗模式 uint8_t sleep_cmd[] = {0xB0, 0x98}; HAL_I2C_Master_Transmit(&hi2c1, SHT31_ADDR, sleep_cmd, 2, HAL_MAX_DELAY); // 唤醒传感器 uint8_t wake_cmd[] = {0x35, 0x17}; HAL_I2C_Master_Transmit(&hi2c1, SHT31_ADDR, wake_cmd, 2, HAL_MAX_DELAY); HAL_Delay(1); // 等待传感器稳定
  • 降低采样频率:根据应用需求调整测量间隔

  • 电源管理:不测量时切断传感器电源

5. 高级应用与扩展

5.1 多传感器组网

通过I2C地址引脚,可以连接多个SHT31传感器:

  1. 地址配置

    • ADDR接GND:0x44
    • ADDR接VDD:0x45
  2. 轮询读取

    float temp[2], humid[2]; SHT31_ReadTempHumid(&temp[0], &humid[0], SHT31_HIGH_REPEAT, 0x44<<1); SHT31_ReadTempHumid(&temp[1], &humid[1], SHT31_HIGH_REPEAT, 0x45<<1);

5.2 与环境光传感器联合使用

典型的环境监测节点往往需要多种传感器:

// 同时读取温湿度和光照强度 float temperature, humidity, lux; void read_sensors() { SHT31_ReadTempHumid(&temperature, &humidity); BH1750_ReadLight(&lux); // 假设已实现光强传感器驱动 // 数据打包处理... }

5.3 云端数据上传

将采集数据通过Wi-Fi或NB-IoT上传:

// 伪代码示例 void upload_to_cloud() { char json[128]; sprintf(json, "{\"temp\":%.1f,\"humid\":%.1f,\"time\":%lu}", temperature, humidity, HAL_GetTick()); // 通过AT指令发送数据 GSM_SendATCommand("AT+HTTPPOST=\"api.example.com\",\"application/json\""); GSM_SendData(json); }

在实际项目中,我发现SHT31的响应速度和高精度使其特别适合需要快速环境反馈的应用场景。通过合理配置重复性模式和采样频率,可以在精度和功耗之间取得良好平衡。对于初次接触I2C通信的开发者,建议先用逻辑分析仪抓取通信波形,直观理解I2C协议的时序要求,这对调试复杂的传感器应用大有裨益。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/11 23:53:52

实时图表架构革命:代码驱动可视化系统的企业级实践

实时图表架构革命&#xff1a;代码驱动可视化系统的企业级实践 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live-editor …

作者头像 李华
网站建设 2026/5/11 23:53:38

QAbstractTableModel进阶实战:构建可编辑数据表格的完整指南

1. 从零理解QAbstractTableModel的核心机制 第一次接触Qt模型视图框架时&#xff0c;很多人会被QAbstractTableModel这个抽象类吓到。但当我真正用它完成第一个可编辑表格后&#xff0c;发现它的设计其实非常优雅。想象你正在开发一个学生管理系统&#xff0c;需要展示包含姓名…

作者头像 李华
网站建设 2026/5/11 23:52:48

别再只会拖模块了!Simulink Editor 里这5个隐藏的高效建模技巧,新手必看

别再只会拖模块了&#xff01;Simulink Editor 里这5个隐藏的高效建模技巧&#xff0c;新手必看 当你第一次打开Simulink Editor时&#xff0c;可能会被它简洁的界面所迷惑——看起来似乎只需要拖拽模块、连接信号线就能完成建模。但当你面对一个包含数百个模块的复杂模型时&am…

作者头像 李华