因科研中需要测量温度和湿度,打算自制了一个温湿度传感器。传感芯片采用的是SHT35,单片机为STM32F103ZET6。工作原理很简单,通过I2C接口向芯片发送指令和采集数据,然后通过USART发送到上位机。先来了解一下传感器。
1. 主要功能
- 全面校准、线性、温度补偿数字输出
- 宽电压工作范围:2.15V-5.5V
- I2C通信接口,最高速度可达1MHz
- 双地址可选。
- 启动和测量速度快
- 8针DFN封装,尺寸:2.5×2.5×0.9mm

图1. 传感器内部功能模块框图
传感器的功能框图如图1所示。内部有一个16位的ADC负责采集温度和湿度传感器的数据,然后通过校准和线性化处理,通过I2C接口与外部通信。整个模块有7个功能引脚:
引脚名称 |
功能说明 |
nRESET |
硬件复位。输入低电平复位;不用时可浮空或通过>2KΩ电阻接到VDD。 |
VDD |
电源正极。接2.15-5.5V,通常接3.3V。 |
VSS |
电源负极。接地。 |
Alert |
报警引脚。温湿度超过限定值时可输出报警信号。不用时必须浮空。 |
SCL |
时钟引脚。接主I2C模块同名引脚。 |
SDA |
数据引脚。接主I2C模块同名引脚。 |
ADDR |
地址引脚。通过该引脚电平高/低,选择模块的通信地址。不能浮空。 |

图2. 传感器芯片典型接线图。
典型接线图如图2所示。R引脚是个空引脚,无电气功能。VDD必须通过一个100nF的电容接地。SCL和SDA需要通过上拉电阻接到VDD。从网上买的焊接好的模块(右下角所示),只引出了6个引脚,nRESET被直接连到了VDD,SCL和SDA的两个上拉电阻均为10kΩ的贴片电阻。另外,Alert引脚也通过一个贴片电容接地,ADDR引脚接了一个10k欧的下拉电阻。模块到手价53,还是比价厚道的价格,SHT35价格还是比较高的,零售价在30元上下。
2. 工作原理
SHT35是I2C接口。工作原理很简单:将MCU的I2C设为Master,芯片的I2C作为Slave,每次读写前,Master首先向Slave发送地址,收到确认信号后再发送(设置、测量、读取等)指令。对读取指令返回的原始数据进行处理、显示或发送到上位机。
根据芯片手册,SHT35有两个地址:ADDR引脚接低电平时,默认地址是0x44;ADDR接高电平时,地址是0x45。这种设计使得多个芯片可以连接到同一条总线上工作,通过ADDR引脚(接GPIO)进行片选。这款芯片采用的是I2C的7-bit地址标准。以ADDR接地为例:写入请求时须将地址左移1位,末位为0,即0x44<<1U;读取请求时,须左移1位然后将末位置1,即(0x44<<1U) | 0x1。这个细节极其重要,否则会因地址错误,导致传感器无应答。
SHT35带CRC校验,所有指令都自带CRC。从机发送数据时,都会计算CRC。完整的读取温度和湿度信息需要6个字节:前2个字节为温度原始数据,第3个为温度数据的CRC,第4-5个字节为湿度原始数据,第6个字节为湿度数据的CRC。如果不需要CRC,软件中可以不进行CRC校验,但SHT35内部是一定会计算和发送CRC的。
所谓的读写指令,就是芯片厂商设计好的一组16位代码。详见下文。
3. 工作模式
1) 单次测量模式:

图3. 单次测量模式相关指令
所谓单次测量(Single shot)模式,就是发一次指令,读一次数据。根据主I2C是否开启时钟延长和测量可靠性高、中、低(平均次数)不同,共有6组指令。如图3所示。
2) 周期性测量模式

图4. 周期性测量指令
所谓周期性测量(Periodic data acquisition)模式,就是发一次测量指令,可以周期性地读取数据。根据可靠性和测量频率(0.5Hz-10Hz)不同,共有15组指令。如图四所示。
周期性测量模式下,发送测量指令后,每次读取数据前必须发送Fetch Data指令:0xE000。周期测量模式下,可以发送ART(Accelerated Response Time)指令:0x2B32进行加速,该指令会强制芯片以4Hz的速度获取数据。
退出周期模式,需发送Break指令:0x3093。退出后芯片会回到单次测量模式。
3) 报警模式
SHT3x系列芯片提供了一个报警模式。在周期性测量模式下,可以利用Alert引脚来监控温湿度是否超过了预设的阈值。如果超过了阈值,Alert引脚的电平会发生变化,同时内置的16-bit状态寄存器的标志位会对报警原因进行标识。比如可以将Alert引脚连接到MCU的中断引脚,当出现环境参数超限时,可以用来唤醒MCU,查询传感器内部状态寄存器确定原因,然后通过外围电路进行相应的响应,例如发出声音、闪灯、提示等。
温度和湿度的报警阈值分别由4个阈值构成。如图5所示:

图5. 报警模式的不同阈值
- HIGH Set:上限报警值。高于该值启动报警,ALERT引脚输出高电平。
- HIGH Clear:清除上限报警值。高于HIGH Set后,回落至该值以下,清除报警。
- LOW Set:下限报警值。低于该值触发报警,ALERT引脚输出高电平。
- LOW Clear:清除下限报警值。低于LOW Set后,回升至该值以上,清除报警。
这种设计可以避免在报警值附近出现快速振荡。
阈值的设置通过向传感器写入一个16-bit的数据来实现,其中高7位为湿度阈值,第9位为温度阈值。由于温度和湿度值也是以16-bit格式来表示的,设置阈值时原始数据与阈值数据的对应关系如图6所示:

图6. 原始数据拼成阈值数据的方法
即,截取湿度值的高7位作为阈值的高7位、温度值的高9位作为阈值的低9位。用程序表示如下:
limitVal = (rawHumidity&0xFE00)|((rawTemperature>>7)&0x001FF);
拼成一个16-bit的值后,用一个命令即可完成设置,可以提高效率。设置阈值时,温度的分辨率约0.5℃,湿度分辨率约1%。
前述4种阈值均按相同的格式进行设置。具体是哪种阈值,则由读/写前的引导命令代码来区分。读和写入阈值的指令代码如图7所示:

图7. 读、写报警阈值的指令代码
复位后,报警阈值会恢复图8所示的初始值。

图8. 报警阈值初始值
特别注意:写入报警阈值时,发送地址后,指令(2bytes)、数据(2bytes)、CRC(1byte)要依次发送过去。发送数据前不能再发送地址。换言之,用HAL_I2C_Master_Transmit函数要一次性发送5个字节。
4) 状态寄存器
传感器芯片内置了一个16-bit的状态寄存器。各功能位释义如下:
位 |
功能说明 |
默认值 |
15 |
报警挂起 0-无挂起报警 1-至少有一个挂起报警 |
1 |
14 |
预留 |
0 |
13 |
加热器状态 0-关闭 1-开启 |
0 |
12 |
预留 |
0 |
11 |
RH报警追踪 0-无湿度报警 1-有湿度报警 |
0 |
10 |
T报警 0-无温度报警 1-有温度报警 |
0 |
9:5 |
预留 |
00000 |
4 |
是否检测到系统复位 0-自上次清除状态寄存器后无复位 1-自上次清除状态寄存器后有复位 |
1 |
3:2 |
预留 |
00 |
1 |
命令状态 0-上一命令成功执行 1-上一命令未执行(无效/CRC不匹配) |
0 |
0 |
CRC写入状态 0-上次CRC写入正确 1-上次CRC写入失败 |
0 |
状态读取指令:0xF32D。
状态寄存器复位指令:0x3041。清除所有状态位(置0)。
5) 其它指令
软件复位指令:0x30A2。该指令使芯片控制器复位并重新加载校准数据。
加热器开/关指令:0x306D/0x3066。内部加热器,仅供芯片测试使用。
另外还有预警阈值设置等。详见手册或官方例程,不再赘述。
搞懂了硬件的工作原理,接下来基于HAL库编写驱程。