☰
SHT3x温湿度传感器驱动详解:I2C时序、CRC校验与工程移植指南
2026/10/15 17:26:53 网站建设 项目流程

简介:面向嵌入式开发工程师的SHT3x温湿度传感器完整示例代码包,适用于环境监测、智能家居、工业自动化等场景,帮助开发者快速实现高精度温湿度采集与上位机通信,也适合刚接触传感器驱动的初学者学习I²C/SPI总线操作与数据解析。压缩包共13个文件,包含4个C源文件、4个头文件、1个STM32启动汇编文件,以及Keil µVision工程文件、代码结构说明PDF和Readme文本,整体仅34KB,便于下载与移植。目前已有997人学习下载,代码中演示了I²C底层读写、命令字发送、温湿度原始数据转换成实际值的完整流程,并对校验和与错误返回做了处理。最关键的是,工程可直接在Keil中打开编译,省去环境搭建时间;源码覆盖初始化、单次/连续测量命令、读取与校验解析等核心步骤,配合PDF文档可快速将SHT3x集成到项目中,实现可靠温湿度监测。

1. 高精度温湿度传感器 SHT3x:这套代码能帮你从跳变的湿度里解脱出来

拆过不少温湿度项目后,我对 SHT3x 高精度温湿度传感器的一个判断是:它解决的问题不是精度本身,而是稳定性——同样的 I2C 命令,有人读出来是稳定的一串小数,有人读出来是每秒跳 3 个百分点的湿度。这套驱动代码把初始化、单次/周期测量、CRC 校验和滤波都包好了,适合正在做环境监测、冷链记录或恒温恒湿控制,又不想逐行啃数据手册的开发者。读完这份拆解,你能判断它靠不靠谱,也能直接把它移植到自己的工程里,少走几段弯路。

2. 读懂 SHT3x 的关键参数:I2C 时序、测量模式与精度边界

2.1 为什么 SHT3x 比 DHT 系列更适合做成产品

自己焊开发板玩的时候,DHT11 也能用,单总线时序靠微秒级延时硬凑,读一个 bit 就得拉高拉低一轮,MCU 的中断稍微一掺和,数据就乱了。但放进产品里,这种"裸奔"式通信没有应答重试机制,一旦时序被破坏,读回来的数据只能丢掉重来。SHT3x 走标准 I2C,从机地址固定为 0x44 或 0x45,主机通过应答位就能判断总线状态,同一个 I2C 总线上还能继续挂气压、光照等其他传感器。

从数据帧来看,DHT 系列一次返回 40 bit,校验只有最朴素的 8 位校验和;SHT3x 每次测量返回 6 个字节,包含温度原始值、湿度原始值和各自的 CRC8 校验,单字节翻转、通信干扰都能被识别出来。这对于长线传输或者工业现场来说,意味着你拿到的每个数据点都是经过合法性验证的,而不是"大概也许对"。

对比项DHT 系列SHT3x 系列
接口单总线,时序敏感标准 I2C,100kHz~1MHz
原始数据8 位整数 + 8 位小数16 位原始值,线性换算
校验8 位校验和,较弱CRC8,按字节校验
扩展功能基本没有加热器、报警引脚、周期测量
防错能力丢 bit 后无法恢复NACK/重发/CRC 三重保障

我一般会把 SHT3x 放在 DHT 前面还有一个原因:驱动分层好做。I2C 读写抽象成几个函数后,换 MCU 平台只需改底层适配,算法层完全不动;单总线方案想做到这种可移植性,得自己封装时序层,而且不同型号的时序参数还不一样。

2.2 测量命令怎么选:单次、周期、重复性背后的时间与功耗

SHT3x 的测量命令是 16 位,通过 I2C 一次写入两个字节。命令字设计得很有规律,同一类功能只是尾字节不同。看数据手册时最容易晕的地方就是命令表太长,实际上只要抓住几个核心命令就行。

命令字功能测量时间适用场景
0x2C 0x06单次测量,高重复性,带时钟延展约 15.5ms精度优先的产品
0x2C 0x10单次测量,中重复性,带时钟延展约 6.5ms平衡功耗与精度
0x2C 0x15单次测量,低重复性,带时钟延展约 2.5ms电池供电
0x24 0x00单次测量,高重复性,不带时钟延展约 15.5ms硬件 I2C 不支持延展时
0x20 0x32周期测量,10 mps,高重复性每 100ms 更新连续监测
0x20 0x22周期测量,2 mps,高重复性每 500ms 更新低功耗轮询

重复性等级不是精度等级,它决定的是测量噪声、测量时间和电流消耗。高重复性下传感器内部会做更多次的模数转换再平均,所以数据更平滑;低重复性适合电池供电的物联网节点,因为每次测量电流消耗能差出 3~4 倍。命令 0x2C 和 0x24 的区别在于是否允许传感器在测量期间拉低 SCL 以延长时钟周期,这个细节在避坑章节里会专门讲,它决定了你的硬件 I2C 外设能否正常配合。

周期测量命令写到 0x20 系列之后,传感器会按照设定频率自动测量,主机只需要按固定的间隔去读取最新结果,不用每读一次都发命令。这个模式适合数据记录仪,能让功耗曲线更平稳,但第一次读数和模式切换的时序有一些坑,后面会展开。

2.3 精度边界:"±2%RH"不是随时都能拿到

数据手册上写的 SHT30 湿度典型精度是 ±2%RH,SHT31 也是 ±2%RH,SHT35 能做到 ±1.5%RH。这里有两个细节容易被忽略:第一,典型值是在 25°C、气流稳定、传感器无热干扰的条件下测出来的;第二,湿度传感器在长期运行后会有漂移,尤其是工作在高温高湿环境里的设备。

实际项目里,决定你能拿到多高精度的往往不是传感器本身,而是 PCB 布局和外壳结构。传感器如果紧挨着 MCU、DC-DC 电感或者 LDO,这些器件的温升会通过 PCB 铜皮传导到传感器,导致湿度读数系统性偏高——因为相对湿度是温度的函数,传感器周围温度每升高 1°C,测到的 RH 就可能偏移 2~3 个百分点。数据手册里的"高精度"三个字,是建立在传感器和热源拉开距离的前提下的。

另外,SHT30、SHT31、SHT35 的命令和数据格式完全兼容,同一份驱动代码可以直接通吃三个型号。区别只在于出厂校准精度等级,普通应用用 SHT30 已经足够,只有做计量级设备才需要上 SHT35。驱动代码里不需要按型号分支,这一点对资源落地来说很友好。

3. 驱动代码实战:从 I2C 适配到单次测量、周期测量的完整拆解

3.1 先看代码结构:一个 HAL 层把平台差异挡住

拿到这套 SHT3x 驱动代码,第一件事不是去读 sht3x.c,而是先看它的平台适配层。质量好的代码包里一定会有一层 HAL(硬件抽象层),把 I2C 读写函数指针化,这样换平台时只需要改几个函数实现,算法层一行不用动。

/* sht3x_hal.h */ #ifndef SHT3X_HAL_H #define SHT3X_HAL_H #include <stdint.h> typedef struct { /* I2C 读函数:从指定地址读取 len 字节到 buf */ int (*i2c_read)(uint8_t dev_addr, uint8_t *buf, uint16_t len); /* I2C 写函数:把 len 字节从 buf 写入指定地址 */ int (*i2c_write)(uint8_t dev_addr, uint8_t *buf, uint16_t len); /* 毫秒延时函数 */ void (*delay_ms)(uint16_t ms); } sht3x_hal_t; #endif /* SHT3X_HAL_H */

这段结构体把 SHT3x 驱动和具体 MCU 解耦开了。回调函数的作用是让驱动代码不直接依赖某个厂商的 I2C 库,STM32 平台你可以把 i2c_read 指到 HAL_I2C_Master_Receive,Linux 平台可以指到 i2c-dev 的文件读写函数,Arduino 平台指到 Wire 库的 requestFrom 搭配 read。

参数说明:dev_addr 是从机地址,SHT3x 固定是 0x44 或 0x45;buf 是数据缓冲区;len 是读写字节数。delay_ms 必须有,因为 SHT3x 的软件复位和测量等待都依赖精确延时,不能省。

在资源包的 example 目录里,通常能看到一个基于 Linux i2c-dev 的 demo,也会有一个基于 MCU 硬件 I2C 的 demo。建议先跑通 Linux 版,因为它不需要烧录和接线,直接在单板上就能验证传感器好坏。

3.2 初始化与软件复位:头两步决定后面稳不稳

传感器上电之后不能立刻发测量命令,需要先软件复位,让传感器内部状态机回到已知状态。

/* sht3x.c —— 初始化部分 */ #define SHT3X_ADDR_ADDR_PIN_LOW 0x44 #define SHT3X_ADDR_ADDR_PIN_HIGH 0x45 #define SHT3X_CMD_SOFT_RESET 0x30A2 int sht3x_init(sht3x_t *dev, sht3x_hal_t *hal) { uint8_t cmd[2]; uint8_t status[3] = {0}; int ret; if (!dev || !hal || !hal->i2c_read || !hal->i2c_write || !hal->delay_ms) return -1; dev->hal = hal; dev->addr = (dev->addr_pin) ? SHT3X_ADDR_ADDR_PIN_HIGH : SHT3X_ADDR_ADDR_PIN_LOW; /* 软件复位 */ cmd[0] = (SHT3X_CMD_SOFT_RESET >> 8) & 0xFF; cmd[1] = SHT3X_CMD_SOFT_RESET & 0xFF; ret = hal->i2c_write(dev->addr, cmd, 2); if (ret < 0) return ret; hal->delay_ms(10); /* 复位后需要至少 1ms,这里留足 10ms */ /* 读取状态寄存器,确认通信链路正常 */ cmd[0] = 0xF3; /* 高字节命令 */ cmd[1] = 0x2D; /* 低字节命令 0xF32D */ ret = hal->i2c_write(dev->addr, cmd, 2); if (ret < 0) return ret; hal->delay_ms(1); ret = hal->i2c_read(dev->addr, status, 3); if (ret < 0) return ret; /* status[2] 是 CRC 校验位,这里先省略校验细节,完整算法在第 4 章 */ return 0; }

这段代码做了三件事:选择从机地址、软复位、读状态寄存器。地址选择通过 addr_pin 字段实现,硬件上 ADDR 引脚接地就是 0x44,接 VDD 就是 0x45,代码层的映射关系必须和原理图一致,否则后面所有通信都会失败。

软件复位命令 0x30A2 的作用是让传感器恢复出厂默认配置,清除周期测量状态,关闭加热器。延时 10ms 是安全余量,数据手册要求复位后至少等 1ms,但实际测试中部分批次的传感器在 5ms 内还不稳定,所以我习惯留 10ms。

读状态寄存器只是为了验证 I2C 链路通没通。如果读回来的三个字节全是 0xFF,说明传感器没应答,优先检查地址和上拉电阻。状态寄存器的完整解析在第 6 章会用到。

3.3 单次测量:命令、等待、读取、校验的四步流程

单次测量是最常用的模式,适合低功耗设备:发命令,等传感器完成测量,读 6 字节数据,校验换算。

/* sht3x.c —— 单次测量 */ #define SHT3X_CMD_MEAS_HIGH_REP_CLOCK_STRETCH 0x2C06 #define SHT3X_MEAS_DELAY_HIGH_REP_MS 20 int sht3x_read_single(sht3x_t *dev, float *temp_c, float *hum_rh) { uint8_t cmd[2]; uint8_t buf[6]; uint16_t raw_t, raw_h; int ret; if (!dev || !temp_c || !hum_rh) return -1; /* 1. 发送测量命令 */ cmd[0] = (SHT3X_CMD_MEAS_HIGH_REP_CLOCK_STRETCH >> 8) & 0xFF; cmd[1] = SHT3X_CMD_MEAS_HIGH_REP_CLOCK_STRETCH & 0xFF; ret = dev->hal->i2c_write(dev->addr, cmd, 2); if (ret < 0) return ret; /* 2. 等待测量完成,高重复性典型 15.5ms,这里延时 20ms */ dev->hal->delay_ms(SHT3X_MEAS_DELAY_HIGH_REP_MS); /* 3. 读取 6 字节:温度高、温度低、温度CRC、湿度高、湿度低、湿度CRC */ ret = dev->hal->i2c_read(dev->addr, buf, 6); if (ret < 0) return ret; /* 4. CRC 校验,失败直接返回错误码 */ if (sht3x_crc8_check(buf[0], buf[1], buf[2]) != 0) return -2; if (sht3x_crc8_check(buf[3], buf[4], buf[5]) != 0) return -3; /* 5. 原始值拼接 */ raw_t = ((uint16_t)buf[0] << 8) | buf[1]; raw_h = ((uint16_t)buf[3] << 8) | buf[4]; /* 6. 线性换算 */ *temp_c = -45.0f + 175.0f * (float)raw_t / 65535.0f; *hum_rh = 100.0f * (float)raw_h / 65535.0f; return 0; }

这段流程是整套驱动最核心的部分。第一步写命令,0x2C 0x06 表示高重复性单次测量且允许时钟延展;第二步等待 20ms,不是随便拍的数字——数据手册写明高重复性测量最长需要 15.5ms,延时不够会导致读取时传感器还没完成内部转换,读出来的原始值可能是不稳定的中间结果;第三步读取 6 字节是固定格式,温度占前两字节,湿度占第四五字节,中间的第三和第六字节是各自的 CRC8。

要注意 raw_t 和 raw_h 都是无符号 16 位整数,不能声明成 int8_t 或者 char,否则左移 8 位时符号位会捣乱。换算公式里的 65535 是 16 位 ADC 的最大计数值,原始值和物理量是按满量程线性对应的,这个公式在数据手册里有明确说明,第 4 章会详细推导。

3.4 周期测量:把采集功耗降下来的同时别丢数据

如果设备需要持续监测,比如恒温恒湿箱,用单次测量意味着每次都要主机主动发起,CPU 被频繁打断。周期测量模式下,传感器自己按设定频率测量并缓存最新结果,主机随时读都能拿到当前最新值。

/* 切换到周期测量:2 mps,高重复性 */ #define SHT3X_CMD_PERIODIC_2MPS_HIGH_REP 0x2236 /* 停止周期测量,回到单次模式 */ #define SHT3X_CMD_BREAK 0x3093 int sht3x_start_periodic(sht3x_t *dev) { uint8_t cmd[2]; cmd[0] = (SHT3X_CMD_PERIODIC_2MPS_HIGH_REP >> 8) & 0xFF; cmd[1] = SHT3X_CMD_PERIODIC_2MPS_HIGH_REP & 0xFF; return dev->hal->i2c_write(dev->addr, cmd, 2); } int sht3x_read_periodic(sht3x_t *dev, float *temp_c, float *hum_rh) { uint8_t buf[6]; uint16_t raw_t, raw_h; int ret; /* 周期模式下不需要发命令,直接读 6 字节 */ ret = dev->hal->i2c_read(dev->addr, buf, 6); if (ret < 0) return ret; if (sht3x_crc8_check(buf[0], buf[1], buf[2]) != 0) return -2; if (sht3x_crc8_check(buf[3], buf[4], buf[5]) != 0) return -3; raw_t = ((uint16_t)buf[0] << 8) | buf[1]; raw_h = ((uint16_t)buf[3] << 8) | buf[4]; *temp_c = -45.0f + 175.0f * (float)raw_t / 65535.0f; *hum_rh = 100.0f * (float)raw_h / 65535.0f; return 0; }

周期模式的核心区别在于:sht3x_start_periodic 只是发送一次模式切换命令,之后传感器会自己按设定频率测量,数据缓存在内部寄存器里。每次读取时主机直接向传感器要数据,不需要再发测量命令,这把每次读取的 I2C 交互从"写命令+等待+读取"三步简化成了一步。

2 mps 就是每秒测量 2 次,500ms 更新一次。如果你的应用要求更快的数据刷新率,可以用 10 mps 的 0x20 0x32,但功耗会相应增加,而且读取频率越快,I2C 总线被占用的时间越多。0x3093 是退出周期模式的命令,退出后传感器回到 idle 状态,低功耗设备在长时间待机前应该执行这个命令。

4. 原始值换算与 CRC 校验:16 位数据怎么变成可信的温湿度

4.1 温湿度公式:为什么是 -45 + 175 × raw / 65535

SHT3x 温湿度原始值与物理量的换算是一次线性映射。温度量程是 -40°C 到 125°C,但数据手册给出的换算起点是 -45°C,留了 5°C 的余量,公式为:T = -45 + 175 × raw_t / 65535。湿度量程是 0%RH 到 100%RH,公式为:RH = 100 × raw_h / 65535。

这两个公式的本质是等比缩放:ADC 把满量程电压量化成 65535 个台阶,每个台阶对应的物理量大小就是量程除以 65535。温度每个 LSB 约等于 0.0027°C,湿度每个 LSB 约等于 0.0015%RH,所以 SHT3x 的分辨率远远高于其精度——你能读出 14 位的小数,但真实精度只有 ±2%RH。

换算时要用浮点数或者定点数,不能直接整数相除。C 语言里 175 * raw_t / 65535 在整数运算下会先乘法后除法,raw_t 最大 65535 时 175 × 65535 已经超过 16 位,要用 uint32_t 过渡或者直接 float 计算。

/* 这份驱动用的换算写法 */ float sht3x_convert_temperature(uint16_t raw_t) { return -45.0f + 175.0f * (float)raw_t / 65535.0f; } float sht3x_convert_humidity(uint16_t raw_h) { return 100.0f * (float)raw_h / 65535.0f; }

两个函数的核心逻辑完全一样,只是温度和湿度的量程范围不同。实际项目中,温度换算后通常会保留一位小数输出,湿度保留一位小数,这样既满足多数场景的显示需求,又不会让浮点字符串处理占用太多 MCU 资源。如果做的是仪表类产品,建议保留两位小数,因为 SHT3x 的原始分辨率支持到这个位数的稳定输出。

4.2 CRC8 校验:读回来的 6 个字节,只有逻辑上检查过才能用

SHT3x 的 CRC8 校验算法是它和普通传感器的重要区别。每个数据字段都由两字节数据和一字节 CRC 组成,CRC 的多项式是 0x31,初始值 0xFF,计算时按位处理,不翻转输入输出。这个算法和很多温湿度传感器的 CRC8 不一样,不能用通用的 CRC8 库直接算,必须按数据手册的规则来。

/* sht3x_crc8 —— 计算两字节数据的 CRC8 */ static uint8_t sht3x_crc8(uint8_t msb, uint8_t lsb) { uint8_t crc = 0xFF; uint8_t data[2] = { msb, lsb }; int i, j; for (i = 0; i < 2; i++) { crc ^= data[i]; /* 每次处理一个字节,先异或 */ for (j = 0; j < 8; j++) { /* 再按位处理 */ if (crc & 0x80) crc = (crc << 1) ^ 0x31; /* 最高位为 1 时与多项式异或 */ else crc <<= 1; /* 最高位为 0 时直接左移 */ } } return crc; } int sht3x_crc8_check(uint8_t msb, uint8_t lsb, uint8_t crc_byte) { uint8_t calc = sht3x_crc8(msb, lsb); return (calc == crc_byte) ? 0 : -1; }

这段代码实现的 CRC 校验原理可以用一句话概括:把两字节数据当成输入流,按位做多项式除法,得到的余数就是 CRC 值 0x31 是该校验多项式的二进制表示。常用的 CRC8 多项式还有 0x07、0x8C 等,SHT3x 选 0x31 意味着它的检错特性与常见传感器不同,移植时不要直接套用通用代码。

实际项目里 CRC 校验失败的原因一般是三个:I2C 时序不稳定导致字节错位、从机地址错误导致读到其他设备的响应、测量未完成时读数导致数据帧不完整。遇到 CRC 连续失败,先不要怀疑算法,用逻辑分析仪抓一下 I2C 波形,看看 SCL 上有没有毛刺、ACK 位是否正常。

4.3 滑动滤波与报警阈值:把跳变的湿度变成可用的数据

SHT3x 的原始数据在湿度变化剧烈时会有 ±0.5%RH 左右的波动,这在通风环境中是正常的物理现象,不是传感器故障。但如果你的控制逻辑每 100ms 就根据湿度值做一次继电器或者加热器动作,这种波动会被放大成控制抖振。解决方案是加滑动平均滤波。

/* sht3x_filter.c —— 8 点滑动平均滤波 */ #define FILTER_WINDOW_SIZE 8 static float filter_buf[FILTER_WINDOW_SIZE]; static uint8_t filter_index = 0; static uint8_t filter_count = 0; float sht3x_sliding_filter(float input) { float sum = 0; int i; filter_buf[filter_index] = input; filter_index = (filter_index + 1) % FILTER_WINDOW_SIZE; if (filter_count < FILTER_WINDOW_SIZE) filter_count++; for (i = 0; i < filter_count; i++) sum += filter_buf[i]; return sum / (float)filter_count; }

这段代码维持一个环形缓冲区,每次新数据进来覆盖最旧的数据,返回窗口中所有数据的平均值。窗口大小 8 意味着输出滞后于真实变化大约 4 个采样周期,在 2 mps 的测量频率下就是 2 秒滞后,对大多数环境监控场景完全够用。

温度数据一般不需要滤波,因为热惯性和传感器自身的热质量已经把高频波动抹平了,再滤波只会增加控制回路的相移。湿度滤波则要慎重选择窗口大小:窗口越大越平滑,但响应越慢。做通风管道监测时,我一般用 4 点窗口;做洁净室这类稳定环境,8 点窗口更合适。报警阈值建议在滤波后的数据上判断,避免误触发,但要注意滤波引入的延时可能让报警晚发生 1~2 秒,对安全敏感的场景要缩短窗口。

5. 常见问题与避坑记录:新手上板最容易翻车的五个细节

5.1 从机地址 0x44 还是 0x45:一上电就 NACK 的元凶

现象:I2C 扫描工具扫描不到传感器,每次 write 都返回 NACK,读出来的数据是 0xFF 或者全 0。

原因:SHT3x 的从机地址由 ADDR 引脚硬件决定。ADDR 接地时地址是 0x44,ADDR 接 VDD 时地址是 0x45。很多开发板默认不焊接 ADDR 引脚的上拉或下拉电阻,导致引脚悬空,传感器可能随机落入某一个地址。另一个常见情况是代码里写死了 0x44,但硬件原理图把 ADDR 接到了 VDD。

解决:先把 ADDR 引脚按照你需要的地址接死,然后写一个 I2C 地址扫描程序,遍历 0x40 到 0x4F,把有 ACK 响应的地址打印出来。这样一次就能确认硬件和代码里的地址是否一致。从那以后我每次拿到新板卡,第一件事永远是扫地址,而不是去读数据。

5.2 时钟延展:用 0x2C 命令反而被 SCL 拉低卡住

现象:使用 0x2C 系列的"带时钟延展"测量命令时,MCU 的硬件 I2C 外设卡死在等待状态,总线上 SCL 一直被拉低,读操作无法完成。软件模拟 I2C 的代码则表现为延时后读到的数据全部是 0xFF。

原因:时钟延展(Clock Stretching)是 SHT3x 的默认行为:传感器在测量期间会主动把 SCL 拉低,告诉主机"我正在忙,请等待"。硬件 I2C 外设如果配置成标准模式且不支持时钟延展,控制器会一直等待 SCL 释放,导致总线卡死;软件模拟 I2C 如果没在主循环里处理"读的时候发现 SCL 拉低就继续等"的逻辑,也会超时。

解决:如果你用的是 MCU 硬件 I2C,先查芯片参考手册确认外设支持时钟延展;如果不支持,改用 0x24 系列的"不带时钟延展"命令,代价是主机必须自己延时足够时间再读取,这份驱动里已经把延时 20ms 写进去了,直接换命令字即可。软件模拟 I2C 的用户,建议在 read 操作里加入 SCL 忙检测循环,而不是盲目固定延时。

5.3 周期模式第一次读数:你拿到的可能是上一次的数据

现象:程序启动时调用 sht3x_start_periodic 后立刻读数据,读出来的温湿度明显不对,甚至固定是 0。

原因:周期测量命令只是把传感器切换到自动测量模式,但第一次测量结果需要经过一个完整的测量周期后才能产生。如果主机在切换后立刻读取,传感器内部的缓冲区还是旧数据或者无效数据,只有等第一个周期完成后,缓存里才是和当前环境匹配的有效值。

解决:周期测量模式启动后,先延时至少一个测量周期再加读取。2 mps 模式下实际测量间隔是 500ms,保险起见延时 600ms;10 mps 模式延时 150ms 就够。更好的做法是读取前检查状态寄存器的数据就绪位,数据手册里 bit15 置 1 表示有新的测量结果可用,这份驱动虽然没有完整的就绪位读取函数,但你可以按第 4 章的 CRC 校验思路自行补一个。

5.4 PCB 布局:传感器和电感靠近,湿度读数会跟着负载飘

现象:设备运行时湿度读数稳定,但电机或者 Wi-Fi 模块一启动,湿度值立刻跳高 2~3 个百分点,随后又回落。

原因:SHT3x 的湿敏电容对温度极其敏感,而 DC-DC 电感、功率放大器和 MCU 在工作时会发热,热量通过 PCB 铜皮传导到传感器封装内,使传感器周围的微环境温度升高。相对湿度是温度的函数,局部温度每升高 1°C,测得的 RH 就会明显下偏移,读数自然就不准了。

解决:PCB 布局时把 SHT3x 摆放在板边或角落,与发热源至少保持 5mm 以上距离;传感器下方尽量避免大面积铺铜,最好把焊盘外的铜皮挖空,减少热传导路径。外壳设计上,给传感器位置开通风孔,让空气流过而不是憋在壳内。如果空间实在紧张,可以在铜皮上开一条隔热槽,或者利用软件滤波把这个热扰动平均掉,但这是治标不治本。

5.5 焊接与洗板:助焊剂会让湿敏电容"喝饱"

现象:新焊接的板子第一次通电湿度读数明显偏高,达到 70%~80%RH,而且长时间不下降。同一批板子中,手工焊接的比机器贴片的更严重。

原因:湿度传感器内部是一个高分子湿敏电容,水汽吸附在感应膜上才能产生电学变化。焊接过程中的助焊剂挥发物和清洗剂残留会附着在感应膜表面,相当于给传感器贴了一层"防水的膜",导致它对外界湿度变化不敏感,读数被异常拉高。SHT3x 芯片本身有防护罩,但防护罩并不是完全密封的。

解决:波峰焊和回流焊后不要立即进行湿度校准,先让传感器在干燥环境中通电运行 24 小时以上,利用传感器自身的加热器(第 6 章会讲)或者在 50°C 烘箱里烘烤 4 小时,让残留物逐步挥发。使用免清洗助焊剂的工艺、焊接后避免用超声波清洗,是保护这个部件的两个最重要的措施。

6. 进阶:用加热器与饱和盐溶液做一次快速体检

6.1 加热器自检与除湿

SHT3x 内置了一个加热电阻,通过命令 0x306D 可以开启,0x306E 关闭。加热器有两个用途:一是做传感器功能自检——正常工作时开启加热器,芯片温度应该明显上升,温度读数会跳高 5~10°C;二是除湿——传感器在潮湿环境中长期运行,湿敏电容可能吸附过多水分导致响应变慢,周期性开启加热器可以蒸发掉膜上的凝结水。加热器功耗有限,不需要担心烧坏传感器,但注意加热期间读取的温度值不能用作环境温度。

6.2 饱和盐溶液的湿度点检

要验证一份驱动代码读出的湿度到底准不准,不需要买昂贵的湿度发生器,只需要一个密封罐和一瓶氯化钠分析纯。饱和氯化钠溶液在 25°C 环境下的相对湿度平衡点是 75.3%RH,这是公开的物理化学常数,常被用作湿度传感器的一级校准点。做法是:把饱和溶液倒入密封罐,传感器悬置在液面上方且不接触液体,密封后静置 12 小时,读取 10 次数据取中位数。如果读数和 75.3%RH 的偏差超过传感器标称精度,优先检查传感器有无污染,其次才是驱动代码的换算公式。这套代码里的 CRC 校验逻辑和滤波窗口,我在做对比测试时完全没有改,直接拿原始读数做均值就通过了点检。从那以后我每次拿到新的传感器批次或者改版 PCB,都会强制走一遍"先扫地址、再读三组原始值、CRC 不过不看数据、滤波参数最后调"的流程。这个习惯帮我省掉了很多玄学排错时间,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询