从零构建STM32F103与SHT31的I2C通信系统硬件连接、软件配置与数据解析全指南在物联网和智能硬件快速发展的今天环境监测已成为众多项目的核心需求。温湿度传感器作为最基础的环境感知元件其稳定可靠的驱动实现是嵌入式开发者必须掌握的技能。本文将带领初学者使用STM32F103系列单片机通过I2C接口与高精度SHT31温湿度传感器建立通信从硬件连接到软件实现逐步构建完整的测量系统。1. 硬件准备与电路连接1.1 所需材料清单主控芯片STM32F103C8T6正点原子Mini开发板传感器模块SHT31-DIS温湿度传感器连接线材杜邦线若干建议使用不同颜色区分信号开发环境Keil MDK-ARM或STM32CubeIDESTM32CubeMX配置工具串口调试助手如Putty、SecureCRT1.2 引脚连接详解SHT31传感器与STM32的硬件连接需要特别注意电平匹配和信号完整性。以下是标准连接方式SHT31引脚STM32引脚功能说明VCC3.3V电源正极GNDGND电源地SDAPC11I2C数据线SCLPC12I2C时钟线提示实际项目中当通信距离超过20cm时建议在SDA和SCL线上各串联一个100Ω电阻并添加2.2KΩ上拉电阻至3.3V以提高信号质量。1.3 硬件连接常见问题排查初次连接时开发者常会遇到以下问题通信失败检查电源电压是否稳定3.3V±5%确认SDA/SCL线序是否正确测量上拉电阻是否正常工作数据不稳定确保电源去耦电容0.1μF靠近传感器VCC引脚检查杜邦线接触是否良好避免与高频信号线平行走线2. 开发环境配置与工程建立2.1 STM32CubeMX基础配置使用STM32CubeMX可以快速生成初始化代码大幅降低开发难度// 在CubeMX中进行如下配置 1. 选择正确的STM32F103C8T6型号 2. 启用I2C1外设或I2C2根据实际连接 3. 配置PC11为I2C_SDAPC12为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 └── Middlewares3. SHT31驱动实现详解3.1 传感器通信协议分析SHT31采用标准I2C协议但有几点特殊之处设备地址0x447位地址测量命令高重复性测量0x2C06中重复性测量0x2C0D低重复性测量0x2C10数据格式温度16位原始数据需按公式转换湿度16位原始数据需按公式转换3.2 核心驱动函数实现以下是完整的传感器驱动实现// sht31.h 头文件定义 #define SHT31_ADDR 0x441 // 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通信稳定性可采取以下措施错误处理机制添加超时重试逻辑实现通信失败后的硬件复位信号质量优化缩短通信线长度添加适当的终端匹配在PCB设计时保持I2C走线远离高频信号软件滤波实现滑动平均滤波设置数据合理性检查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传感器地址配置ADDR接GND0x44ADDR接VDD0x45轮询读取float temp[2], humid[2]; SHT31_ReadTempHumid(temp[0], humid[0], SHT31_HIGH_REPEAT, 0x441); SHT31_ReadTempHumid(temp[1], humid[1], SHT31_HIGH_REPEAT, 0x451);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(ATHTTPPOST\api.example.com\,\application/json\); GSM_SendData(json); }在实际项目中我发现SHT31的响应速度和高精度使其特别适合需要快速环境反馈的应用场景。通过合理配置重复性模式和采样频率可以在精度和功耗之间取得良好平衡。对于初次接触I2C通信的开发者建议先用逻辑分析仪抓取通信波形直观理解I2C协议的时序要求这对调试复杂的传感器应用大有裨益。