基于STC89C51的双通道DHT11温湿度实时显示系统设计与实现

发布时间:2026/10/14 0:06:33
基于STC89C51的双通道DHT11温湿度实时显示系统设计与实现 简介这份资源面向电子工程、嵌入式入门与课程设计人群提供一套基于STC89C51单片机的双通道DHT11实时温湿度显示系统完整工程。系统以STC89C51为控制核心通过单总线读取两路DHT11温湿度数据经时序解析后由LCD1602液晶实时显示并配套按键模块覆盖传感器采集、字符屏驱动与人机交互等典型环节。压缩包共22个文件约68KB包含C语言源码与头文件、Keil工程及编译产物、HEX烧录文件、硬件模块代码和说明文本目录按HARDWARE、LCD、KEY、USER等模块划分便于对照理解工程结构。目前已有1372人学习下载。读者可据此获得可直接编译烧录的参考工程、模块化代码组织方式与调试排错思路适合作为单片机课程设计、毕业设计或嵌入式入门练手案例帮助快速掌握传感器驱动与显示控制的完整流程。1. 双通道 DHT11 温湿度系统为什么老单片机反而更适合做实时显示很多人第一次看到“基于 STC89C51 的双通道 DHT11 实时温湿度显示系统”这个标题第一反应是都什么年代了怎么还在用 51 单片机但如果你真的在工厂车间、农业大棚、仓库或者机房做过环境监测就会发现一个反直觉的事实——越是需要长期稳定运行、不需要联网、不需要复杂算法的场景STC89C51 这类老芯片反而越省心。它便宜、抗干扰能力强、代码量小、不需要操作系统上电就跑断电再来也不丢状态。这个系统要解决的核心问题很具体同时采集两个位置的温度和湿度在 LCD1602 上实时刷新显示。双通道的意义在于很多场景下你关心的不是“当前温度是多少”而是“两个位置的温差和湿度差是多少”。比如一个密闭机柜内外、一个温室大棚的南北两端、一个仓库的入口和深处。单点测量只能告诉你一个数字双通道才能让你看出趋势和差异。适合读这篇的人有三类一是正在做单片机课程设计或毕业设计的学生需要一套能跑通、能讲清楚、能复现的方案二是刚转行做嵌入式开发的工程师想找一个完整的小项目练手三是在实际工作中需要快速搭建环境监测原型的从业者。接下来的内容会从硬件连接、DHT11 时序、LCD1602 驱动、双通道调度策略到实际调试中会遇到的坑一步步拆开讲。2. 硬件选型与最小系统搭建为什么是 STC89C51 加两颗 DHT112.1 主控芯片的选型理由与最小系统电路STC89C51 是 8051 内核的经典增强型单片机相比原版 8051它内置了更大的 Flash 和 RAM支持串口下载不需要专用编程器。对于这个项目来说它的资源刚好够用两颗 DHT11 各占一个 IO 口LCD1602 用 4 位或 8 位并行接口占用 6 到 11 个 IO剩下的 IO 还可以接按键或者蜂鸣器做报警扩展。最小系统需要的东西不多一颗 STC89C51、一个 11.0592MHz 或 12MHz 的晶振、两个 30pF 左右的起振电容、一个复位电路10uF 电容加 10K 电阻、一个电源滤波电容。晶振选 11.0592MHz 的好处是串口波特率更准虽然这个项目不一定用串口但如果你后续想加串口上传数据这个频率会省去很多麻烦。电源部分要注意DHT11 的工作电压是 3.3V 到 5.5VSTC89C51 是 5V 系统所以直接共用 5V 供电没问题。但如果你用 USB 供电要注意 USB 口的电流输出能力两颗 DHT11 加上 LCD1602 背光总电流大概在 30mA 到 50mA 之间一般的 USB 口都能带动。2.2 DHT11 的引脚定义与上拉电阻的取值DHT11 有两种封装三针模块和四针裸传感器。三针模块已经集成了上拉电阻直接插线就行四针裸传感器需要自己接。四针的引脚定义是VCC、DATA、NC空脚、GND。注意不同厂家的排列顺序可能不一样拿到手先用万用表测一下别凭记忆接线。DATA 引脚必须接一个上拉电阻典型值是 4.7K 到 10K。这个电阻的作用是在总线空闲时把电平拉高因为 DHT11 的数据线是开漏输出没有上拉电阻的话总线会浮空单片机读到的全是随机值。我一般用 4.7K通信成功率比 10K 高一些尤其是在线缆较长的时候。如果你要把 DHT11 放在离单片机较远的地方比如一米以上建议用屏蔽线并且在 DATA 和 GND 之间加一个 100nF 的电容做滤波。线缆越长分布电容越大上拉电阻就要越小但太小会增加功耗4.7K 是一个比较平衡的值。2.3 LCD1602 的 4 位接口接法与对比度调节LCD1602 支持 8 位和 4 位两种并行接口模式。8 位模式占用 8 个数据口传输速度快但浪费 IO4 位模式只用 4 个数据口分两次传一个字节速度慢一半但对于这个项目来说完全够用。我一般用 4 位模式省下来的 IO 可以接按键或者继电器。4 位模式的接线是LCD 的 D4 到 D7 接单片机的 P2.4 到 P2.7RS 接 P2.0RW 接 P2.1E 接 P2.2。RW 引脚其实可以接地因为大多数情况下我们只写不读接地可以省一个 IO。但如果你要用忙标志判断就需要接 IO。我一般接 IO因为忙标志判断比延时更可靠。对比度调节用一个 10K 的电位器一端接 VCC一端接 GND中间抽头接 LCD 的 V0。调节的时候慢慢转直到字符清晰为止。如果怎么调都不清晰检查一下背光是否正常背光不亮的话字符是看不见的。3. DHT11 单总线时序拆解从启动信号到 40 位数据的完整读取3.1 启动信号与响应信号的时序要求DHT11 的通信协议是单总线主机和从机轮流控制数据线。一次完整的通信过程是主机拉低总线至少 18ms然后释放从机检测到后拉低总线 80us 作为响应再拉高 80us然后开始传输数据。这里的关键参数是主机拉低时间不能少于 18ms否则 DHT11 可能不响应从机响应信号的低电平时间是 80us高电平时间也是 80us。如果你的单片机晶振是 12MHz一个机器周期是 1us用延时函数可以比较精确地控制这些时间。// 主机启动信号拉低至少 18ms void DHT11_Start(void) { DHT11_PIN 0; // 拉低数据线 Delay_ms(20); // 延时 20ms留余量 DHT11_PIN 1; // 释放总线 Delay_us(30); // 等待 20-40us让从机拉低响应 }这段代码的逻辑是先把数据线拉低 20ms确保 DHT11 能检测到启动信号然后释放总线延时 30us 后开始检测从机的响应信号。延时 30us 是因为从机检测到启动信号后会在 20us 到 40us 内拉低总线如果延时太短可能还没等到响应就误判了。3.2 40 位数据的位判定与校验和计算DHT11 一次传输 40 位数据分成 5 个字节湿度整数、湿度小数、温度整数、温度小数、校验和。校验和等于前四个字节相加的低 8 位。对于 DHT11 来说小数部分通常都是 0因为它的精度只有 1%RH 和 1℃。每一位数据的判定方法是从机先拉低总线 50us 表示位开始然后拉高总线高电平持续 26us 到 28us 表示数据 0持续 70us 表示数据 1。所以主机在检测到低电平结束后延时 40us 再读总线电平如果还是高电平就是数据 1否则是数据 0。// 读取一个字节 unsigned char DHT11_ReadByte(void) { unsigned char i, byte 0; for (i 0; i 8; i) { while (!DHT11_PIN); // 等待 50us 低电平结束 Delay_us(40); // 延时 40us跳过数据 0 的高电平 byte 1; // 左移一位 if (DHT11_PIN) { // 如果还是高电平说明是数据 1 byte | 1; while (DHT11_PIN); // 等待数据 1 的高电平结束 } } return byte; }这段代码的核心是延时 40us 后的采样点。数据 0 的高电平只有 26us 到 28us延时 40us 后已经变成低电平数据 1 的高电平有 70us延时 40us 后还是高电平。这个时间窗口是 DHT11 协议里最关键的参数延时太长或太短都会导致误判。3.3 双通道分时复用的调度策略两颗 DHT11 不能同时读取因为单总线协议要求主机独占总线。我一般用分时复用的方式先读第一颗间隔至少 1 秒后再读第二颗。DHT11 的采样周期是 1 秒如果读得太快它会返回上一次的数据或者不响应。// 双通道读取调度 void Read_Both_Sensors(void) { if (DHT11_Read(temp1, humi1) 0) { // 读第一颗 // 更新 LCD 第一行显示 } Delay_ms(1200); // 间隔 1.2 秒 if (DHT11_Read(temp2, humi2) 0) { // 读第二颗 // 更新 LCD 第二行显示 } }这里的 1.2 秒间隔是留了余量的。DHT11 手册上写的是采样周期不低于 1 秒但实际测试中有些批次的传感器在 1 秒整的时候会返回错误数据1.2 秒比较稳妥。如果你要同时显示两个通道的数据LCD 的刷新也要跟着这个节奏走不能刷太快否则屏幕会闪。4. LCD1602 驱动与显示刷新怎么让四个数据稳定不跳4.1 4 位模式下的写命令与写数据时序LCD1602 的 4 位模式每次传一个字节要分两次先传高 4 位再传低 4 位。每次传输都要拉低 E 引脚保持一段时间再拉高形成使能脉冲。RS 引脚决定是写命令还是写数据RS 为 0 是命令RS 为 1 是数据。// 写一个字节到 LCD4 位模式 void LCD_WriteByte(unsigned char dat, unsigned char rs) { LCD_RS rs; // 选择命令或数据 LCD_RW 0; // 写模式 LCD_D4 (dat 4) 0x01; // 高 4 位 LCD_D5 (dat 5) 0x01; LCD_D6 (dat 6) 0x01; LCD_D7 (dat 7) 0x01; LCD_E 1; // 使能脉冲 Delay_us(5); LCD_E 0; Delay_us(100); // 等待命令执行 // 低 4 位同理 }这段代码里E 引脚的高电平时间不能太短至少 450ns我一般给 5us留足余量。命令执行时间根据命令不同而不同清屏命令需要 1.52ms其他命令一般 37us 到 100us。我统一用 100us 延时虽然有点浪费但稳定。4.2 温湿度数据的格式化与显示位置规划LCD1602 有两行每行 16 个字符。我一般这样规划第一行显示通道 1 的数据格式是“T1:25C H1:60%”第二行显示通道 2 的数据格式是“T2:26C H2:58%”。这样一眼就能看出两个通道的差异。// 格式化显示 void Display_Data(unsigned char temp, unsigned char humi, unsigned char line) { unsigned char buf[16]; if (line 0) { sprintf(buf, T1:%dC H1:%d%%, temp, humi); LCD_SetCursor(0, 0); } else { sprintf(buf, T2:%dC H2:%d%%, temp, humi); LCD_SetCursor(1, 0); } LCD_WriteString(buf); }用 sprintf 的好处是格式化方便缺点是占用 Flash 空间。STC89C51 的 Flash 一般有 4K 到 8Ksprintf 大概占 1K 左右如果空间紧张可以自己写一个简单的整数转字符串函数。4.3 刷新频率与闪烁抑制的实操参数LCD 刷新频率太高会导致屏幕闪烁太低又显得反应迟钝。我一般用 500ms 到 1s 的刷新周期。但双通道读取需要 2.4 秒左右每颗 1.2 秒所以实际刷新周期是 2.4 秒。这个速度对于环境监测来说完全够用温度和湿度不会在几秒内剧烈变化。如果你觉得 2.4 秒太慢可以缩短间隔到 1 秒但要注意 DHT11 的采样周期限制。另一个办法是用两个独立的定时器分别控制两颗 DHT11 的读取但这样代码复杂度会上升对于 51 单片机来说不太划算。提示LCD 的背光电流较大如果直接用单片机 IO 驱动可能会拉低电压导致单片机复位。建议用三极管或者 MOS 管驱动背光或者直接接限流电阻到 VCC。5. 避坑与排查双通道 DHT11 系统最常见的五个翻车现场5.1 现象LCD 显示乱码或只显示一行黑块原因对比度电位器没调好或者 LCD 初始化时序不对。LCD1602 上电后需要等待至少 15ms 才能发送命令如果初始化太快内部控制器还没准备好就会显示异常。解决在初始化函数开头加 50ms 延时然后发送 0x388 位模式或 0x284 位模式三次每次间隔 5ms。对比度电位器慢慢调直到字符清晰。如果还是不行检查 RS、RW、E 三根线有没有接反。5.2 现象DHT11 返回的温湿度全是 0 或者 255原因上拉电阻没接或者 DATA 线接错了引脚。DHT11 的数据线在没有上拉电阻的情况下会浮空单片机读到的全是高电平或者随机值。另外有些三针模块的引脚顺序是 VCC、DATA、GND有些是 DATA、VCC、GND接反了也会读不到数据。解决用万用表测 DATA 线在空闲时的电压正常应该是 VCC 电压。如果接近 0V说明上拉电阻没接或者接错了。检查引脚顺序确保 VCC 接 5VGND 接 GNDDATA 接单片机 IO。5.3 现象两颗 DHT11 只有一颗能读到数据原因两颗 DHT11 共用了一个 IO 口或者读取间隔太短。单总线协议要求主机独占总线如果两颗传感器接在同一个 IO 上会互相干扰。另外如果读取间隔小于 1 秒DHT11 可能还没完成上一次采样返回的是旧数据或者不响应。解决每颗 DHT11 单独占一个 IO 口读取间隔至少 1.2 秒。如果 IO 不够用可以用模拟开关切换但会增加硬件复杂度。我一般建议直接用两个 IOSTC89C51 的 IO 足够多。5.4 现象数据偶尔跳变比如温度突然变成 80 度原因电源纹波太大或者 DATA 线受到干扰。DHT11 对电源质量比较敏感如果和电机、继电器共用电源纹波会导致通信错误。另外DATA 线太长或者没有屏蔽也会引入干扰。解决在 DHT11 的 VCC 和 GND 之间加一个 100nF 的陶瓷电容靠近传感器引脚放置。DATA 线如果超过 20cm用屏蔽线屏蔽层接地。电源部分加一个 100uF 的电解电容做储能。5.5 现象程序跑一段时间后死机LCD 不再刷新原因看门狗没开或者中断冲突。51 单片机没有内置看门狗如果程序跑飞就会死循环。另外如果用了定时器中断中断服务函数里做了太多事情会导致主循环卡死。解决加一个外部看门狗芯片比如 MAX813或者用软件看门狗定时器溢出后复位。中断服务函数里只做标志位设置具体处理放到主循环里做。DHT11 的读取函数里加了 while 等待如果传感器不响应会一直等建议加超时计数。6. 从能跑到好用双通道温湿度系统的三个进阶技巧6.1 用滑动平均滤波让显示值不再跳DHT11 的精度是 1℃但实际读数经常会在两个值之间跳比如 25 和 26 交替出现。这不是传感器坏了而是它的分辨率和噪声导致的。最简单的解决办法是滑动平均连续读 5 次去掉最大值和最小值剩下的取平均。// 滑动平均滤波 unsigned char Filter_Temp(unsigned char new_val) { static unsigned char buf[5] {0}; static unsigned char idx 0; unsigned char i, max, min, sum 0; buf[idx] new_val; if (idx 5) idx 0; max buf[0]; min buf[0]; for (i 0; i 5; i) { if (buf[i] max) max buf[i]; if (buf[i] min) min buf[i]; sum buf[i]; } return (sum - max - min) / 3; // 去掉最大最小后取平均 }这个函数的逻辑是维护一个 5 个元素的缓冲区每次新数据进来替换最旧的数据然后去掉最大值和最小值剩下的 3 个取平均。这样既能抑制突发噪声又不会让响应变得太慢。对于温度这种变化缓慢的物理量5 点滤波足够了。6.2 加一个温差报警用蜂鸣器做阈值提示双通道系统的一个实用功能是温差报警当两个通道的温度差超过设定阈值时蜂鸣器响。这个功能在农业大棚里特别有用比如南北两端温差超过 3℃ 就说明通风不均匀。// 温差报警 void Check_Temp_Diff(unsigned char t1, unsigned char t2) { unsigned char diff; if (t1 t2) diff t1 - t2; else diff t2 - t1; if (diff 3) { // 温差超过 3℃ BEEP 0; // 蜂鸣器响 } else { BEEP 1; // 蜂鸣器停 } }阈值 3℃ 是我根据大棚场景定的你可以根据实际需求改。如果是机房温差超过 5℃ 才需要报警如果是冷库温差超过 2℃ 就要注意了。蜂鸣器建议用有源蜂鸣器直接给电平就响不需要 PWM 驱动。6.3 把数据存到 EEPROM断电后还能看历史STC89C51 内部有 EEPROM可以用来存历史数据。比如每分钟存一次温湿度存满 24 小时的数据大概需要 2K 字节。这样即使断电重新上电后也能看到之前的趋势。// 存数据到 EEPROM void Save_To_EEPROM(unsigned char temp, unsigned char humi, unsigned int addr) { ISP_CONTR 0x81; // 使能 ISP/IAP ISP_CMD 0x02; // 写命令 ISP_ADDRH addr 8; ISP_ADDRL addr 0xFF; ISP_DATA temp; ISP_TRIG 0x46; // 触发序列 ISP_TRIG 0xB9; // 等待写完成然后存湿度 }这段代码是 STC 系列单片机 EEPROM 操作的标准流程。注意写 EEPROM 需要时间大概 20ms 左右写太频繁会影响主循环的实时性。我一般 1 分钟存一次一天存 1440 条每条 2 字节总共不到 3KSTC89C51 的 EEPROM 一般有 4K 以上够用。注意EEPROM 的擦写次数有限大概 10 万次左右。如果 1 分钟写一次一年就是 52 万次会超过寿命。建议用循环存储的方式或者降低存储频率到 5 分钟一次。我自己做这个系统的时候最开始没加上拉电阻调了两个晚上才发现是硬件问题血泪经验就是DHT11 不响应先查上拉电阻再查时序。后来加了滑动平均滤波显示稳定多了不会再出现 25 和 26 来回跳的情况。如果你也在做类似的项目建议先把单通道跑通再加第二通道不要一上来就搞双通道否则出了问题很难定位是硬件还是软件。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询