尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
SHT3x温湿度传感器驱动开发:从原理到避坑全指南
简介SHT3x 温湿度传感器代码包面向嵌入式开发初学者与物联网应用工程师围绕盛思锐 SHT3x 高精度温湿度传感器提供一套基于 STM32 平台的完整示例工程帮助解决环境监测、智能家居、工业自动化等场景中温湿度数据精确采集与解析的难题。压缩包共 13 个文件大小 34KB核心代码为 4 个 C 源文件和 4 个头文件另含汇编启动文件、Keil µVision 工程文件、PDF 结构说明与 Readme 使用指引导入工程即可编译调试。目前已有 997 人学习下载。通过源码可以系统掌握传感器初始化、I²C 通信时序、测量命令发送、原始数据读取及温湿度值换算的完整流程配套 PDF 详解代码组织与配置方法Readme 提供入门说明便于快速定位关键函数并移植到其他硬件平台为后续集成与二次开发节省大量时间。1. 一块几块钱的传感器代码却卡住大半个项目SHT3x 温湿度传感器在嵌入式项目里几乎是“默认选项”体积小、功耗低、精度够用。实际调试中却常出现这种情况——传感器能读到数但湿度偶尔跳到 99%或者温度比室温高 3℃查到最后发现是命令时序和校验环节偷懒了。SHT3x 的测量代码并不复杂核心就是发送命令、等待转换、读出 6 字节并用 CRC 校验但这三个步骤里任何一步不严谨都会让数据变得“正常但不可信”。这篇笔记按“原理 → 最小驱动 → 参数调整 → 踩坑 → 进阶验证”的顺序整理出一套可复现的 SHT3x 采集方案。新手可以跟着把驱动跑通熟手可以直接看第 5 章的排查清单。2. 读懂 SHT3x 的测量模式代码结构由命令时序决定SHT3x 默认通过 I2C 通信但它的工作方式分单次和周期两种代码结构差异很大。先把测量模式理解清楚后面写驱动才不会出现“发命令位置不对、读数据读到旧值”的问题。2.1 单次测量与周期测量是两条完全不同的代码路径单次测量模式下主控每次发送一条测量命令传感器完成一次转换后进入空闲状态。命令可以指定是否允许时钟拉伸如果允许拉伸传感器在转换期间会主动拉低 SCL通知主机“请稍等”如果禁止拉伸主机就只能自己算好转换时间延时够了再读数据。所以单次模式代码是典型的“请求-响应”结构发命令、延时、读数据、校验。任何一个环节出错都容易定位。周期测量则完全不同。传感器以固定速率持续转换数据在内部不断刷新主机想取数时直接发送“读取测量值”命令读回当前结果。周期模式适合屏幕显示、低功耗唤醒这类需要“数据随时可用”的场景但代码里必须有状态判断否则可能读到上一次的旧值。更麻烦的是周期模式下你并不知道传感器此刻是在转换中还是已经就绪很多总线卡死和 CRC 错误都出在这个模糊地带。实际选择有一个朴素原则如果你只是 1 秒采一次或者还在调试排障用单次模式更好因为它独立、可控、出错好定位。如果系统要求传感器“一直热着”数据随时可拿才值得换周期模式。很多翻车现场都是单次模式的代码里套用了周期模式的读取逻辑或者反过来。2.2 必须记住的命令字和 CRC 多项式SHT3x 的命令都是 16 位发送时先发高字节再低字节。代码里我会保留下面这几个最小命令集注释里写清用途命令字用途说明0x30A2软复位传感器僵死时兜底用0xF32D读状态寄存器检查自检结果、命令状态0x2C06单次测量高重复性时钟拉伸转换期间传感器拉低 SCL0x2C24单次测量高重复性非时钟拉伸主控自己延时后读数0xE000周期模式读取测量值周期模式下取数0x306D开启加热器防凝露场景用0x3066关闭加热器加热完毕必须关CRC 校验是 SHT3x 代码里最容易被忽略的一环。传感器对每 16 位原始数据附一个 CRC 字节温度占 3 字节、湿度占 3 字节合在一起就是每次读取 6 字节。CRC 采用 CRC-8/MAXIM 风格多项式 0x31初始值 0xFF既不需要反转输入也不需要反转输出。下面是按位实现配合寄存器资源吃紧的 MCU 也能跑static uint8_t sht3x_crc8(uint8_t *data, size_t len) { uint8_t crc 0xFF; for (size_t i 0; i len; i) { crc ^ data[i]; for (uint8_t bit 0; bit 8; bit) { if (crc 0x80) crc (crc 1) ^ 0x31; else crc 1; } } return crc; }这个函数按字节喂数据每个字节都按多项式 0x31 逐位右挪。参数 len 对 SHT3x 来说每次传 2 即可因为温度原始数据和湿度原始数据都是 16 位。换成查表法在速度上会更快但按位版本更容易读懂、移植时不容易出错。注意不要只校验数据而不处理失败。CRC 不过时要丢弃本次结果不能把坏数据交给业务层否则温湿度偶尔跳变就会被当成传感器硬件问题。2.3 地址引脚决定 I2C 地址代码里不能写死SHT3x 的 ADDR 引脚电平决定设备地址接地时是 0x44接 VCC 时是 0x45。很多人在面包板上用跳线帽换地址后忘记重启设备导致连续读不到传感器。代码里建议把地址统一成宏管理不要散落在各个函数里。#define SHT3X_ADDR_0 (0x44 1) /* ADDR 接地 */ #define SHT3X_ADDR_1 (0x45 1) /* ADDR 接高 */这里 0x44 是 7 位地址左移一位后变成 8 位地址包含 R/W 位。不同 MCU 的 I2C 库对地址的接受方式不一样有的收 7 位地址有的收 8 位地址。我习惯统一在宏里转成 8 位地址这样换个平台驱动代码不用改只是 check 一下底层库的约定。另外如果总线上同时挂了多颗 SHT3x就要通过 ADDR 引脚区分。此时建议在硬件上把引脚电平固定住不要悬空悬空会导致上电瞬间地址不确定最后表现为“时而读到 0x44 时而读到 0x45”。这种偶发问题最难排查不如一开始就用跳线或电阻固定电平。3. 从零写最小驱动I2C 初始化、测量命令与 CRC 校验一条龙这一章进入可复现代码。驱动设计成“平台相关层 传感器逻辑层”两部分底层 I2C 读写函数由具体 MCU 提供上层代码只关心命令、数据、校验和换算。3.1 先写标准的 I2C 读写函数假设底层已经封装好两个接口它们的原型如下int user_i2c_write(uint8_t dev_addr, uint8_t *buf, uint16_t len); int user_i2c_read(uint8_t dev_addr, uint8_t *buf, uint16_t len);dev_addr传 8 位地址buf是数据缓冲区len是字节数。两个函数返回 0 表示成功非 0 表示失败。不同厂家的库可能提供复合接口write_then_read但封装成两个函数后上层代码可以保持平台无关。接着封装 SHT3x 的命令发送和普通读数据static int sht3x_send_cmd(uint8_t addr, uint16_t cmd) { uint8_t buf[2]; buf[0] (uint8_t)(cmd 8); buf[1] (uint8_t)(cmd 0xFF); return user_i2c_write(addr, buf, 2); } static int sht3x_read_bytes(uint8_t addr, uint8_t *buf, uint16_t len) { return user_i2c_read(addr, buf, len); }写命令时先发高字节这是 SHT3x 的固定时序。如果高低字节写反传感器不会应答或读回的数据全是 0xFF。很多第一次移植失败都是这个问题。3.2 单次测量流程发送命令、等待转换、读回 6 字节以下用非时钟拉伸的高重复性单次测量为例这是最稳、兼容性最好的用法#define CMD_MEASURE_NOHOLD 0x2C24 /* 高重复性非时钟拉伸 */ typedef struct { uint8_t addr; int16_t temperature_x100; /* 实际温度乘以 100 */ uint16_t humidity_x100; /* 实际湿度乘以 100 */ } sht3x_t; static int16_t sht3x_convert_temp(uint16_t raw) { return (int16_t)(((int32_t)raw * 17500) / 65535 - 4500); } static uint16_t sht3x_convert_humi(uint16_t raw) { return (uint16_t)(((uint32_t)raw * 10000) / 65535); } static int sht3x_measure_nonhold(sht3x_t *dev) { uint8_t data[6]; uint16_t raw_t, raw_h; uint8_t crc_t, crc_h; if (sht3x_send_cmd(dev-addr, CMD_MEASURE_NOHOLD) ! 0) return -1; /* 高重复性转换时间典型 12ms最长 15ms */ platform_delay_ms(15); if (sht3x_read_bytes(dev-addr, data, 6) ! 0) return -2; raw_t ((uint16_t)data[0] 8) | data[1]; crc_t data[2]; raw_h ((uint16_t)data[3] 8) | data[4]; crc_h data[5]; if (sht3x_crc8(data[0], 2) ! crc_t || sht3x_crc8(data[3], 2) ! crc_h) return -3; dev-temperature_x100 sht3x_convert_temp(raw_t); dev-humidity_x100 sht3x_convert_humi(raw_h); return 0; }命令 0x2C24 表示高重复性、非时钟拉伸单次测量。选择非时钟拉伸是为了避免传感器拉低 SCL 后某些 MUC 的 I2C 外设不擅长处理这种等待状态。平台延时 15ms 是按高重复性的最大转换时间取的上限中重复性约 6ms、低重复性约 3ms但工程上统一用高重复性更省心15ms 的延时代价在绝大多数应用里可以忽略。温度和湿度换算用了纯整数运算。温度公式是 -45 175 × raw / 65535为了返回实际温度乘以 100改写成(raw * 17500) / 65535 - 4500。湿度公式是 100 × raw / 65535乘以 100 后用(raw * 10000) / 65535。这样避免了浮点运算在低成本 MCU 上更有优势误差不超过 0.02℃。3.3 数据换算把原始值变成带单位的温湿度上面的代码已经调用换算函数。单独拆出来是为了方便做单元测试也方便以后扩展成浮点版本。换算函数在 3.2 中已经给出这里补一点使用建议temperature_x100是int16_t存的是实际温度 × 100例如 2323 表示 23.23℃负温度也能正常表达。humidity_x100是uint16_t存储值范围 010000显示时除以 100 即可。打印到日志或屏幕时建议保留一位小数即可SHT3x 的湿度分辨率本身就是 0.01%RH没必要展示满打满算。CRC 校验失败时函数返回 -3。调用方不要忽略返回值至少要在日志里记一笔。很多“偶尔跳变”的现场问题靠的就是这个错误码统计才定位到总线干扰。4. 把代码调稳测量模式、加热器与滤波参数的取舍驱动能读到数只是第一步真正影响体验的是参数选择。这一章讲三个高频选择重复性、滑动平均窗口、加热器要不要开。4.1 测量重复性参数怎么选耗时、噪声和功耗的平衡SHT3x 的重复性分低、中、高三档对应转换时间大约 3ms、6ms、15ms。高重复性噪声更低适合长期记录和标定低重复性响应快适合快速扫描。如果系统每秒采一次建议直接固定高重复性因为功耗差异微乎其微而数据质量差别能直接看得到。有些代码为了省电把每次测量都设成低重复性结果湿度波动明显变大。实际上单次测量的功耗本身就在微安级对电池供电的产品来说关键是降低测量频率而不是反复压缩单次转换时间。所以我的习惯是低频采集优先保证质量高频采集才考虑用中低重复性。4.2 滑动平均滤波的窗口多大合适温湿度传感器本身有随机噪声加上环境微小波动原始数据会抖动。滑动平均是最稳妥的滤波手段窗口大小直接决定响应速度和平滑程度。参考下表窗口长度平滑效果响应速度适用场景4一般快快速记录保留变化细节8较好中室内环境监测16平稳慢长时间平均仓储类监测窗口 8 是大多数场景的折中点。实现上可以用环形缓冲维护累加和避免每次求平均都遍历窗口#define FILTER_WIN 8 static uint32_t sum_temp_x100 0; static uint16_t buf_temp_x100[FILTER_WIN]; static uint8_t idx_temp 0; static uint8_t cnt_temp 0; static uint16_t filter_update(uint16_t new_val, uint32_t *sum, uint16_t *buf, uint8_t *idx, uint8_t *cnt) { if (*cnt FILTER_WIN) { buf[*idx] new_val; *sum new_val; (*cnt); } else { *sum - buf[*idx]; buf[*idx] new_val; *sum new_val; } *idx (*idx 1) % FILTER_WIN; return (uint16_t)(*sum / *cnt); }这个函数的逻辑是窗口未满时直接加入累加和窗口满后新值进来先减掉最旧的值再加新值。cnt用来处理前几个数据不足窗口长度的情况避免除以 0。注意累加和sum要用uint32_t因为温度 × 100 后最大值约 13000窗口 8 时总和约 104000虽然uint16_t勉强装得下但窗口一旦扩大到 16 或 64 就会溢出提前用 32 位是习惯。4.3 加热器在防凝露场景里要不要开SHT3x 内置加热器可以给传感器局部升温用于排除冷凝水、潮湿环境恢复。但加热期间温度读数会明显偏高它不是用来测环境温度的。什么时候开如果设备会经历结露比如户外机柜、冷链箱在检测到湿度持续高企且温度接近露点时开启加热器一段时间再关掉等传感器回稳然后继续正常测量。我一般建议加热周期设 15 秒关闭后等 10 秒以上再取数否则读到的温度会比环境高不少。还有一点容易被误解加热器不能当作“自检”恒开开了就必须关否则传感器温度长期偏高加速老化且耗电。提示加热器命令是 0x306D 开、0x3066 关。开关后都需要读一次状态寄存器确认状态位但实际代码里很少有人这么做省事一点的做法是开关后固定延时 2ms 再继续。5. SHT3x 调试避坑从地址错误到湿度跳变的五个典型问题这一章是我在调 SHT3x 时最容易踩的坑按出现概率排序。每条都按“现象 → 原因 → 解决”来写方便对照排查。5.1 传感器无应答先查地址再查电源现象调用读写函数返回失败示波器上看不到 ACK或者读回的数据全为 0xFF。原因最常见是 I2C 地址不匹配。SHT3x 有 0x44 和 0x45 两个地址由 ADDR 引脚决定。硬件上把 ADDR 接地代码里却用 0x45自然无应答。其次是供电问题SHT3x 供电必须在 2.4V 到 5.5V 区间内如果 VDD 引脚纹波过大传感器也会偶发无响应。解决先用 I2C 扫描函数或逻辑分析仪确认总线上实际出现的地址再对照代码宏。然后检查 VDD 和 GND 之间是否放了 100nF 去耦电容没有的话加上。最后确认 SDA/SCL 上拉电阻在 1k 到 10k 之间过大的上拉在总线电容高时拉不上去。5.2 CRC 校验频繁失败多半是没等转换完成现象读回数据时 CRC 错误率很高但偶尔还能读到一组看起来合理的值。原因发送单次测量命令后立即读取传感器还没完成转换或者转换命令要求时钟拉伸但主机库不支持等待导致读到半更新状态的数据。还有一种情况是延时设在了转换时间边界上比如高重复性转换需要 15ms 最长代码只延时了 10ms。解决把延时加到最大转换时间之上。高重复性用 15ms中重复性用 7ms低重复性用 4ms。如果是周期模式不要每次发送启动命令而是用 0xE000 直接读测量值同时检查状态寄存器里的数据就绪位。读状态寄存器命令是 0xF32D返回的 16 位状态中某一位标记数据是否就绪具体位号以数据手册为准。5.3 湿度读数停在 100% 或反复跳变先排查环境与焊点现象湿度长时间显示 100%或者在几十秒内跳变超过 10%RH。原因传感器周围局部湿度饱和比如探头沾了水、结露、贴膜没撕也可能是 PCB 焊接残留助焊剂受潮后导电改变了湿度读数。供电噪声大时湿度跳变也会更剧烈。解决先看环境把传感器放在通风处避开呼吸、热气出口。再看硬件用酒精清洗焊点烘干后再测确保走线避开电源开关节点。软件层面可以加滤波但治标不治本。如果换一颗传感器对比后故障消失那就是旧探头本身的问题。5.4 I2C 总线卡死SDA 被拉低后不恢复现象程序在某个 I2C 操作后卡死复位 MCU 后仍然失败逻辑分析仪显示 SDA 一直被拉低。原因传感器在异常时序下进入错误状态或者主机时钟线被干扰打断导致从机一直等待一个不存在的时钟边沿。某些 I2C 外设遇到 NACK 后也不会自动复位状态机于是总线被锁死。解决在初始化阶段增加总线恢复流程先释放 SDA再把 SCL 翻转 9 次最后发一个 STOP。也可以直接对传感器执行软复位 0x30A2。代码里每个读写调用都要加超时超时后调用总线恢复函数。这能避免大多数“运行几个月后突然死掉”的现场问题。5.5 长期运行后无响应软复位命令兜底现象设备连续运行几天后传感器突然无响应断电重启后恢复但复现时间不确定。原因可能源于 I2C 总线竞争、供电瞬断或传感器内部状态机跑飞。这类问题很难在台架上一次复现属于典型的运行期黑匣子问题必须用代码兜底。解决在主循环里做一个健康检查连续读 3 次失败就发送软复位命令 0x30A2延时 20ms 后再重新初始化如果仍然失败记录错误码并再次初始化 I2C。软复位会保留设备地址和配置是安全兜底。注意软复位后至少等 1ms 再发测量命令否则可能不生效。6. 进阶技巧用状态机调度周期采集并拿 24 小时数据验证可靠性6.1 用状态机代替阻塞式延时裸机环境下每次阻塞 15ms 等传感器转换会让 MCU 浪费大量时间尤其是在已经有屏幕刷新、按键扫描和通信协议栈的时候。更优雅的做法是把采集流程拆成状态机。简单来说定义 IDLE、START_CONV、WAIT_CONV、READ_DATA、CRC_FAIL 几个状态。IDLE 时判断采集周期是否到了到了就发送测量命令并切到 WAIT_CONVWAIT_CONV 里用定时器 tick 计数判断 15ms 是否过去过去后发送读命令并切到 READ_DATAREAD_DATA 里读回数据、做 CRC 校验和换算然后回到 IDLE同时记录本次耗时。CRC 错误时切到 CRC_FAIL做一次计数连续多次失败再触发软复位。这种结构比阻塞式代码复杂一点但好处很明显测量过程不再阻挡其它任务超时和复位逻辑也更容易加。我现在写 SHT3x 驱动只要是上 RTOS 或定时器调度一律先用状态机把流程搭出来再往里塞具体实现。6.2 与标准温湿度计做对比误差怎么算才可信代码写完别急着上线先做 24 小时对比验证。把 SHT3x 和标准温湿度计放在同一个空间避免阳光直射和气流干扰每小时记录一组数据。采集时不要只用瞬时值取 10 分钟均值更合理因为传感器和标准表的响应速度不同。计算平均偏差和标准差能帮你判断数据是否可信温度平均偏差在 ±0.5℃以内、湿度在 ±3%RH 以内基本没问题如果标准差偏大先排查硬件布局和滤波窗口。比如湿度标准差大于 3%RH多半是探头局部出现了微小气流而不是传感器本身坏掉。对比验证的另一个作用是确认代码里的换算单位没有用错。我曾经因为换算了两次温度读数整体高了 1.5℃单看数据很“平稳”但一对比标准表就露馅了。现在我的习惯是任何新的 SHT3x 驱动都会先写一个五分钟连续采样统计把最小值、最大值、平均值打印出来确认没有毛刺再交给业务层。这个习惯帮我挡掉了不少后期才暴露的问题希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

C8051F与Keil的DFP驱动包:从设备识别到C2调试的完整排坑指南

C8051F与Keil的DFP驱动包:从设备识别到C2调试的完整排坑指南

简介:这是一份面向使用SILICON LABS C8051F系列单片机并在KEIL环境下开发的配套驱动资源包,适合嵌入式工程师、单片机爱好者及需要搭建C8051F调试环境的开发者。资源重点解决通过USB转串口连接目标板时,CP210x驱动缺失、版本不兼容导致下载与…

📅 2026/10/15 18:34:11
RabbitMQ 官方教程多语言代码仓库(rabbitmq-tutorials)实战指南

RabbitMQ 官方教程多语言代码仓库(rabbitmq-tutorials)实战指南

示例工程 【免费下载链接】rabbitmq-tutorials Tutorials for using RabbitMQ in various ways 项目地址: https://gitcode.com/gh_mirrors/ra/rabbitmq-tutorials 点击查看 免费下载 本篇技术指南围绕开源仓库 rabbitmq-tutorials 展开,它是 RabbitMQ …

📅 2026/10/15 18:34:11
部署 Hermes Agent:Windows 原生与 WSL2 完全指南(TaoToken 统一 Key 接入)

部署 Hermes Agent:Windows 原生与 WSL2 完全指南(TaoToken 统一 Key 接入)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/15 18:34:11
MORE NEWS

更多资讯

📰

用 Swift 和 SpriteKit 打造可二次开发的 Flappy Bird 工程样板

简介:面向iOS游戏开发初学者的Flappy Bird Xcode工程源码包,基于SpriteKit框架用Objective-C编写,可直接用Xcode打开编译,完整呈现经典小游戏从物理模拟到交互响应的开发链路。压缩包共58个文件、约507KB,内容以Object…

📰

脑机接口(BCI)硬核对决:NextMind 9通道多电极 vs 脑智科技 VisionBCI 单通道干电极

近年来,非侵入式脑机接口(BCI)技术逐渐从实验室走向公众视野。在众多技术路线中,基于稳态视觉诱发电位(SSVEP, Steady-State Visually Evoked Potential)的方案因其无需漫长的意念训练、即戴即用的特点&…

📰

MATLAB实战FP-Growth关联规则挖掘:从建树到规则生成

简介:这份资源是面向数据挖掘初学者与MATLAB使用者的FP-Growth关联规则挖掘实现包,用于在交易数据中高效发现频繁项集并提取关联规则,适合市场篮子分析、网络行为分析等场景的入门实践。压缩包共8个文件,以7个.m脚本和1个.mat数据…

📰

大模型算法岗三面面试真题复盘:从Transformer到DeepSpeed分片

简介:这份资料整理了字节跳动大模型算法岗位一面、二面、三面的完整面试题目,面向准备冲击大厂算法岗的求职者,尤其是已有一定深度学习基础、希望系统梳理大模型知识体系的中高级候选人。内容覆盖Transformer与LLaMA的LN差异、RMSNorm与FFN结…

📰

ARMCC编译器实战:Cortex-M老工程选型、编译与避坑

简介:ARM Compiler Version 5(ARMCC)是ARM官方推出的32位ARM架构编译工具链,面向嵌入式开发者、单片机工程师及需要针对Cortex-A/R/M系列进行底层优化的技术人员。它整合了编译器、汇编器、链接器与调试组件,支持C/C源…

📰

外贸主动获客工具大比拼:海关数据、社媒爬虫插件与 AI 工作台,谁才是成单之王?

在外贸圈,有一句老话:“坐等询盘是等死,主动出击才有肉吃。” 为了帮团队主动开发海外客户,外贸老板们几乎把市面上的获客工具试了个遍:从几千块一年的海关数据查询网,到几百块的谷歌地图/领英邮箱抓取插件…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬