news 2026/9/12 3:27:24

仓库自动报警系统:DS18B20单总线与HS1101频率采集实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
仓库自动报警系统:DS18B20单总线与HS1101频率采集实践

简介:这是一份面向嵌入式开发、单片机应用及仓库环境监控学习者的完整项目包,整合DS18B20温度采集、HS1101/GP2D12红外测距、ADC0832模数转换与报警逻辑,覆盖从传感器数据采集到处理显示的关键环节。压缩包共46个文件,约802KB,包含C源码、H头文件、Proteus仿真工程(pdsprj)、Keil工程文件、hex固件、Word说明文档及编译中间文件,便于直接打开工程对照学习或二次开发。资源同时提供演示版仿真与最终版工程目录,可快速理解1602液晶显示、74HC595扩展等模块的协同工作方式。已有741人学习下载,适合课程设计、毕业设计或仓库安防项目起步参考。

1. 仓库自动报警系统为什么要把 DS18B20 和 HS1101 放一起

仓库里最容易被忽视的故障,不是设备不转,而是温度早就越界、湿度已经逼近露点,却没有任何一路报警触发。把 DS18B20 和 HS1101 放进同一个自动报警系统里,本质上不是“读一个温度、再读一个湿度”那么简单:DS18B20 走单总线时序输出数字温度,HS1101 是电容式湿度传感器,必须靠 555 振荡电路转成频率信号才能被单片机识别,两路采集链路完全不同。这篇内容把传感器选型、硬件接线、时序驱动、阈值判定到现场部署串成一条可复现的路径,适合正在做仓库、档案室、机房或冷库环境监控的工程师,也适合拿这套方案改造自己的单片机入门项目。

2. DS18B20 单总线与 HS1101 频率输出:两路采集链路的设计边界

2.1 温度走数字时序,湿度走频率,两者的差异决定程序怎么写

DS18B20 是数字温度传感器,全部数据交换都发生在 1-Wire 单总线上。主机先发复位脉冲,DS18B20 回一个存在脉冲,然后按位读写 ROM 命令和功能命令,每一位的读或写都对应一个约 60us 的时隙。12 位分辨率下温度每 LSB 对应 0.0625℃,转换时间最长 750ms。这条链路的优势是单线供电通信、抗干扰能力强、线拉到两三米仍然能稳定读温度,代价是软件时序严格,位操作期间一旦被中断抢走 CPU,这一帧数据基本作废。

HS1101 本身是一枚电容式相对湿度传感器,电容随湿度上升而增大,没有标准数字接口。常见做法是把它接进 555 定时器的振荡回路,让湿度变化表现为输出频率变化,再由单片机测频。事故集中在两个边界:DS18B20 的误差源于时序窗口被压缩,HS1101 的误差源于频率抖动和电源波动。下面这张对比表直接决定程序资源分配。

对比项DS18B20 温度链路HS1101 + 555 湿度链路
输出形态1-Wire 数字时序方波频率
采集原理主机按时隙读写寄存器输入捕获测周期或定时计数
精度风险时隙偏差、中断打断毛刺、555 供电波动、计数窗口太短
温度补偿无额外需求电容受温度影响,需用 DS18B20 修正
典型耗时12 位转换 750ms测 100 个周期约 10ms

这张表能解释大部分读数异常问题。有人把 DS18B20 的延时函数写进定时器中断,中断频繁抢占导致时序错乱,温度偶尔读出 85℃——那是 DS18B20 上电复位后的默认值,说明主机读到了尚未完成转换的数据。

2.2 采集周期怎么分配:DS18B20 转换期间正好去测 HS1101

DS18B20 启动温度转换后,主机不需要干预总线,只要等待。12 位分辨率下这个等待窗口最长 750ms,是整个采集循环里最耗时的一段。把 HS1101 的频率测量放在这个窗口里执行,单次温湿度采集循环就能压在 1 秒以内,不额外增加报警判定延迟。

HS1101 的湿度采样有两种思路。一种是测周期,用输入捕获抓相邻两次上升沿的时间差;另一种是在固定门控时间内数脉冲。555 电路输出的频率通常在几千赫兹到十几千赫兹,测周期更合适;频率更高时数脉冲更划算。我一般优先用输入捕获测周期,连续读 10 个周期取中值,单次湿度读数 10ms 内完成,完全塞得进 DS18B20 的转换等待窗口。

整体时间预算这样排:复位 DS18B20 并启动温度转换 → 在 750ms 等待窗口里测量 HS1101 周期 → 返回读 DS18B20 暂存器 → 合并数据做温度补偿 → 进入报警判定。如果仓库里挂了多个 DS18B20,不要逐个“启动转换再等待 750ms”串行处理,那会把循环时间拉长到几秒以上;正确做法是统一发启动转换命令,等一次 750ms,再按 ROM 地址逐个读数据,总耗时仍然只有 750ms 左右。

3. 自动报警系统的硬件接线:DS18B20 上拉与 HS1101 振荡电路

3.1 最简单的 HS1101 湿度采集电路:555 定时器做频率变换

HS1101 不能直接接单片机 ADC,因为它的电容变化量换算成电压后太小。典型方案是把 HS1101 当作 555 定时振荡回路里的定时电容:湿度升高,电容变大,充放电时间变长,输出频率下降;湿度降低,频率上升。555 选型上,我建议用 TLC555 而不是 NE555,TLC555 是 CMOS 工艺,静态电流小、输出边沿陡、振荡频率受电源波动影响更小,适合需要精确测频的嵌入式采集端。

电路连接不复杂:HS1101 一端接地,另一端同时接 555 的 THR 和 TRIG 引脚,RA 电阻接 VCC 到 THR/TRIG,RB 电阻接 THR 到 DIS,OUT 引脚输出方波到单片机的输入捕获引脚。HS1101 没有正负极之分,但引线尽量短,否则 PCB 走线和接头上的寄生电容会叠加到传感器电容上,压缩湿度的频率变化范围,导致分辨率下降。

3.2 信号接线顺序和最小系统清单

焊接和接线顺序会直接影响调试效率。先把单片机最小系统、电源、下载器跑通,再焊 HS1101 振荡电路,最后接 DS18B20 到串口打印验证。这样每一步都有明确输出,不需要一次性排查多个故障点。

信号接到 MCU 哪个引脚关键参数说明
DS18B20 DQ开漏输出 GPIO上拉 4.7kΩ 到 VCC线长超过 1m 换 2.2kΩ
HS1101 振荡输出定时器输入捕获引脚高电平不能超过 MCU 耐压5V 供电时需分压或电平转换
GND与 MCU 共地短而粗555 的 VCC 走独立支路
继电器控制任意 GPIO + ULN2003续流二极管并联线圈不要用 GPIO 直接驱动继电器

上拉电阻是 DS18B20 部分最常调整的参数。标准是 4.7kΩ,但总线挂多个传感器或线缆过长时,分布电容变大,上拉太弱会让数据线上的上升沿变缓,主机采样时读到错误电平。我一般先把线长控制在 1 米以内用 4.7kΩ,延长到 2~3 米时直接换 2.2kΩ,同时把时序延时空余量加大。

3.3 555 电路里的 4 个必调参数

第一是 RA 和 RB 的阻值,它们决定振荡中心频率。阻值取 100kΩ 级别、HS1101 电容在 160pF 到 220pF 之间时,输出频率落在几千赫兹到十几千赫兹范围。程序只关心上升沿计数,占空比不需要精确控制,但 RB 不能取太大,否则振荡会变得不稳定。

第二是电源去耦。555 开关瞬间从 VCC 抽取电流,会引起输出频率抖动。在 555 的 VCC 和 GND 之间放 0.1uF 陶瓷电容,再用 10Ω 电阻把 555 的电源与单片机数字电源隔开,这是成本最低也最有效的稳定手段。频率测量最怕电源上叠加高频噪声,计数结果会跟着噪声一起跳。

第三是信号整形。如果输出信号传输距离较长、边沿变缓,单片机会出现多次误触发。TLC555 的推挽输出边沿通常够用;复杂电磁环境下可在 MCU 输入端加一个 74HC14 施密特反相器整形,逻辑电平翻转一次,程序无需改动。

第四是电平匹配。很多仓库系统用 5V 给 555 供电,配合 3.3V 的 STM32 或 ESP32,直接把 5V 高电平灌进输入捕获引脚有损坏风险。常见做法是 TLC555 也用 3.3V 供电,或者在信号线上串联 10kΩ 限流电阻、再并在 MCU 侧 5.1kΩ 电阻到地,把高电平分到 3.3V 以下。

4. 读取 DS18B20 时序与测量 HS1101 周期的 C 代码

4.1 DS18B20 时序驱动:复位、写时隙、读时隙

单总线协议的核心全在微秒延时和采样窗口里。下面这段代码用三个基本操作组装出完整读温度流程。delay_us 在 STM32 上建议用 DWT 计数器实现,不要用依赖主频和编译优化的空循环,否则优化等级一变时序就乱。

#define DQ_PIN GPIO_PIN_7 #define DQ_PORT GPIOA void ds18b20_reset(void) { /* 拉低 480us 产生复位脉冲,释放后等待从机存在脉冲 */ HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_RESET); delay_us(480); HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_SET); delay_us(60); /* 读到低电平说明总线上有 DS18B20 应答 */ if (HAL_GPIO_ReadPin(DQ_PORT, DQ_PIN) == GPIO_PIN_RESET) { delay_us(420); /* 等待存在脉冲走完,保持后续时序对齐 */ } } void ds18b20_write_bit(uint8_t bit) { HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_RESET); if (bit) { delay_us(5); /* 写1:短暂拉低后立即释放 */ HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_SET); delay_us(55); /* 补满整个写时隙 */ } else { delay_us(55); /* 写0:持续拉低整个时隙 */ HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_SET); delay_us(5); } } uint8_t ds18b20_read_bit(void) { uint8_t bit; HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_RESET); delay_us(1); /* 起始脉冲 1us 以上 */ HAL_GPIO_WritePin(DQ_PORT, DQ_PIN, GPIO_PIN_SET); delay_us(8); /* 释放后在采样窗口内读取电平 */ bit = HAL_GPIO_ReadPin(DQ_PORT, DQ_PIN); delay_us(50); /* 补满 60us 读时隙 */ return bit; }

这段代码的逻辑是把每一位都当作一个完整 60us 的时隙,写 1 和写 0 的区别只在低电平持续时间。读时序时主机先拉低再释放,从机决定拉低或释放总线,主机必须在释放后约 15us 内完成采样,否则读到的可能是一个时隙的电平。复位流程里的存在脉冲不是必须读取的,但通过它可以判断传感器是否在线,避免后续读出 0xFFFF 时还要猜测原因。

参数说明:写 1 的低电平建议 1~15us,写 0 的低电平尽量拉满到 60us 附近;读采样窗口定在释放后约 15us 处。每个时隙结束后留 1us 以上恢复时间。完整读温度命令序列是:复位 → 0xCC 跳过 ROM → 0x44 启动温度转换 → 等待最多 750ms → 复位 → 0xCC → 0xBE 读暂存器 → 连续读取 2 字节。低字节和高字节拼成 16 位有符号数后乘以 0.0625 即得摄氏度。

4.2 HS1101 湿度频率采集:输入捕获测周期

HS1101 的湿度换算不依赖某个固定公式,而靠标定。先把 555 输出信号接入定时器输入捕获通道,记录相邻两次上升沿的定时器计数值,周期等于两次捕获值的差,再补上定时器溢出部分。这种测周期方式比固定窗口计数更适合几 kHz 到十几 kHz 的信号。

uint32_t ic_value[2], overflow_cnt = 0; uint32_t period_tick; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { ic_value[0] = ic_value[1]; ic_value[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); period_tick = ic_value[1] - ic_value[0] + overflow_cnt * 65535; /* 补上两次捕获间的定时器溢出 */ } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { overflow_cnt++; /* 16 位定时器溢出计数 */ } }

溢出计数器是这段代码最容易出错的部分。16 位定时器在 72MHz 主频下溢出极快,如果两次上升沿之间定时器溢出多次而程序没补偿,捕获差值会变成负数,算出来的频率完全不可信。用 32 位定时器可以省掉这个分支,但低成本的 STM32F1 系列没有那么多 32 位定时器,这个补溢出的逻辑必须保留。如果信号的单个周期非常长,可以把定时器分频系数调大,比如 72MHz 分频到 1MHz,那么 period_tick 直接就是微秒数,后续频率计算更直观。

湿度换算用两点线性插值公式:

RH = RH_low + (f_low - f_measured) / (f_low - f_high) * (RH_high - RH_low)

f_low 和 RH_low 是一组标定点,f_high 和 RH_high 是另一组。标定方法:把 HS1101 和一只经过校准的温湿度计放进同一个密封袋,先记录当前环境的频率与湿度计读数,再用饱和盐溶液在袋内建立高湿环境,记录第二组数据。两点定出的直线在 20%~90%RH 区间内足够仓库报警使用。标定完成后还要用 DS18B20 的温度做温漂补偿,因为 HS1101 的电容值本身会随温度漂移;补偿系数建议做成可配置项,现场对标后调整。

HS1101 换算参数取值示例说明
输入捕获时基1MHz,即 1us/tick频率越低,周期测量精度越高
标定低点RH=33% 附近用 MgCl2 饱和盐溶液建立
标定高点RH=75% 附近用 NaCl 饱和盐溶液建立
温度补偿每摄氏度修正约 0.1%RH具体系数以实测拟合为准

5. 自动报警判定:回差、去抖与温湿度变化率联合防误报

5.1 双传感器报警阈值表怎么定

仓库报警阈值要按货物类型去定,不能一套参数走天下。电子元器件仓库常把温度控制在 10~30℃、相对湿度 40%~70%RH;纸品档案库对湿度更敏感,上限压到 60%RH。下面的模板可以先跑起来,观察一周再根据误报情况收窄。

判定项阈值示例恢复条件作用
温度上限30℃低于 28℃,回差 2℃联动排风扇
温度下限10℃高于 12℃,回差 2℃联动加热器
湿度上限70%RH低于 66%RH,回差 4%RH联动除湿机
湿度下限40%RH高于 45%RH,回差 5%RH加湿或告警
变化率5 分钟升 5℃ 或升 10%RH指标回到正常持续 30 分钟火情或漏水预判
去抖时间连续 3 个采样周期确认出现正常值立即清零滤掉单次毛刺

回差的含义是触发值和恢复值之间留一个差值,避免设备在阈值附近反复启停。温度到 30℃ 时排风扇启动,降到 29.9℃ 就停,这种情况下温度大概率反弹回 30℃,继电器会持续抖动;把停止条件放到 28℃,设备动作次数会明显下降。湿度通道读数比温度更容易跳变,所以湿度相关的回差要比温度留得更大。

5.2 从正常到报警再到恢复的状态机实现

报警逻辑不建议写成多层 if-else,我用一个三态状态机:NORMAL、ALERT、ALARM。NORMAL 状态下连续 N 个采样周期超限,状态进入 ALERT;ALERT 下指标继续超限则进入 ALARM,触发蜂鸣器和继电器输出;ALARM 必须满足全部恢复条件且持续一段时间才回到 NORMAL。这样单次尖峰不会直接触发报警动作。

typedef enum { STATE_NORMAL, STATE_ALERT, STATE_ALARM } AlarmState; AlarmState update_ledger(AlarmState cur, uint8_t over, uint8_t *counter) { switch (cur) { case STATE_NORMAL: if (over) { (*counter)++; if (*counter >= 3) { /* 连续 3 次采样超限进入预警 */ *counter = 0; return STATE_ALERT; } } else { *counter = 0; } break; case STATE_ALERT: if (over) { return STATE_ALARM; /* 预警期仍超限,直接报警 */ } *counter = 0; return STATE_NORMAL; case STATE_ALARM: if (!over && (*counter)++ >= 3) { return STATE_NORMAL; /* 连续 3 次正常才恢复 */ } break; } return cur; }

温度路和湿度路分别调用这个状态机,最后合并成设备动作。合并时用 OR 逻辑:温度或湿度任一处于 ALARM,蜂鸣器都响;但设备联动要分开判断,温度高只开排风扇,湿度高只开除湿机。注意 ALERT 进入 ALARM 不需要重复去抖,因为前面已经用 3 个采样周期确认过;ALARM 恢复时反而要多确认几次,防止传感器读数在恢复阈值附近来回摆动。

5.3 联动排风扇、除湿机时的防抖和最短动作间隔

联动设备除了回差,还要加一个最小动作间隔。继电器切换后至少等 60 秒才允许下一次切换,这样即使读数值在阈值附近缓慢振荡,设备也不会跟着高频动作,能明显延长继电器触点和压缩机寿命。

typedef struct { uint16_t last_action_ms; /* 上次继电器动作时间 */ uint8_t relay_on; /* 当前继电器状态 */ } RelayCtrl; uint8_t relay_try(RelayCtrl *r, uint16_t now, uint8_t want) { if (now - r->last_action_ms < 60000) { return r->relay_on; /* 未到最小间隔,保持原状态 */ } if (want != r->relay_on) { r->last_action_ms = now; r->relay_on = want; } return r->relay_on; }

这里的时间戳直接取单片机启动后的毫秒 tick,无符号减法在溢出后仍然能得到正确差值,不需要做特殊处理。把“报警状态”和“设备动作”拆成两层,报警状态负责信息呈现,继电器动作负责执行,中间用最小间隔过滤,联动逻辑清晰很多。还有一类特殊情况值得注意:冷库门打开时温度先掉、湿度先猛增,按湿度上限去开除湿机效果很差。常见处理是温度和湿度变化率同时超限时,先只报警不联动,等温湿度趋稳后再按正常阈值决定设备动作。

6. 现场部署的四个细节:从 DS18B20 时序余量到 HS1101 防凝露

6.1 把 DS18B20 的时序余量留在线缆而不是延时里

软件延时不要压到理论最小值。写 1 时隙的低电平时间从 1us 放宽到 5us,读采样窗口从理论的 15us 提前到 13us,这样在长线、低温、电源波动下仍有足够裕量。线缆超过 2 米时用双绞线,上拉换成 2.2kΩ,并避免与继电器驱动线走同一个线管,防止继电器吸合瞬间的干扰串进单总线。

6.2 HS1101 探头要防凝露,不能贴墙安装

仓库里凝露发生时,HS1101 表面结出水膜,电容瞬间接近满量程,湿度读数几秒内冲到 95%RH 以上。这个读数本身是真实的,但会误触发漏水级报警。安装时探头朝下或侧向放置,保持通气但不积水,距离墙面至少 5cm,定期检查探头表面有没有灰尘覆盖。湿度传感器被灰尘堵住气孔后,响应速度会明显变慢。

6.3 湿度和温度补偿要绑定同一个采样周期

DS18B20 转换期间正好采集 HS1101 周期,两路数据的时间戳必须尽量接近,否则用温度修正湿度时会出现几十秒的错位。修正系数按每摄氏度 0.1%RH 的量级起步,现场用标准温湿度计对比后调整,不要直接照搬手册典型值。同一台设备上运行两周后的修正系数,才是这套系统真正可靠的参数。

6.4 用假信号源验证频率通道,先别急着调阈值

调试湿度通道时,临时用一个 100kΩ 电位器配合固定电容替代 HS1101,从低湿到高湿扫一遍,确认程序里频率换算方向正确、报警点能触发,再换回真实传感器。现场用这个方法能快速区分问题在硬件电路还是软件换算。如果是批量部署,我会先在样机上用标准温湿度计做三点标定,确认线性插值在中段没有明显偏差,再复制给其他节点,这样每台设备的标定成本能降下来。

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

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

Agent开发的本质:从命令式编程到声明式状态流的范式跃迁

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

作者头像 李华
网站建设 2026/9/12 3:24:30

STM32嵌入式AI编程:开发流程断点与人工校验红线

1. 这不是“用AI写代码”&#xff0c;而是重构嵌入式开发的认知边界我第一次在Keil里把AI生成的UART初始化函数直接粘贴进工程时&#xff0c;编译器报了17个错误——不是语法错&#xff0c;是硬件抽象层&#xff08;HAL&#xff09;版本不匹配、时钟树配置冲突、GPIO复用功能未…

作者头像 李华
网站建设 2026/9/12 3:24:09

COMSOL偶极子天线散射体仿真:远场方向图畸变与参数分析

做射频仿真的人&#xff0c;十有八九会遇到这么个情况&#xff1a;天线单独仿真时指标漂亮得不行&#xff0c;一放进整机里就立马翻脸。增益掉了、方向图歪了、谐振点飘了&#xff0c;怎么看怎么别扭。最典型的困扰之一&#xff0c;就是天线旁边多了个金属散射体之后&#xff0…

作者头像 李华
网站建设 2026/9/12 3:23:38

Fay 数字人框架:从克隆到跑通只需 3 步,把大模型接进数字人

Fay 数字人框架&#xff1a;从克隆到跑通只需 3 步&#xff0c;把大模型接进数字人 【免费下载链接】Fay fay是一个帮助数字人&#xff08;2.5d、3d、移动、pc、网页&#xff09;或大语言模型&#xff08;openai兼容、deepseek&#xff09;连通业务系统的agent框架。 项目地址…

作者头像 李华
网站建设 2026/9/12 3:23:20

OBS训练营:技术人才培养的创新实践与效果评估

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

作者头像 李华