51单片机实战:DHT11温湿度数据采集与LCD1602/串口双显示
2026/4/18 18:10:32 网站建设 项目流程

1. 项目背景与硬件准备

第一次用51单片机做温湿度监测时,我对着DHT11传感器发愁——这玩意儿怎么才能把数据同时显示在LCD屏和电脑上?后来发现双显示方案才是调试神器。LCD1602负责现场直观查看,串口助手记录历史数据,两者结合能快速定位问题。下面我就把踩坑总结的经验分享给大家。

DHT11这款蓝色小模块堪称性价比之王,20块钱就能买到5个装。虽然精度不如DHT22,但家用和教学场景完全够用。它的单总线协议特别适合51单片机这种IO资源紧张的芯片,只需要1个GPIO引脚就能通信。我实测过在3米长的杜邦线下依然能稳定传输,不过建议控制在1米内更保险。

硬件清单要准备这些:

  • STC89C52RC开发板(带USB转TTL芯片的最方便)
  • DHT11温湿度传感器(注意买3.3V/5V兼容版本)
  • LCD1602液晶屏(建议选蓝底白字款,比黑绿屏更清晰)
  • 面包板+杜邦线若干
  • USB转TTL模块(如果开发板没有内置)

接线时有个易错点:DHT11的数据脚要接10K上拉电阻,否则可能无法启动。我第一次没接电阻,传感器死活不响应,后来查手册才发现这个隐藏要求。LCD1602的VO引脚记得接电位器调对比度,不然显示会一片模糊。

2. 数据采集核心代码解析

DHT11的通信协议看似简单,实际调试时却暗藏玄机。它的单总线时序要求非常严格,微秒级的延迟偏差都会导致读取失败。下面这段起始信号代码我反复调试了十几次才稳定:

void DHT11_start() { Temp_data = 1; DHT11_delay_us(2); Temp_data = 0; DHT11_delay_ms(20); // 保持低电平18ms以上 Temp_data = 1; DHT11_delay_us(13); // 等待20-40us }

关键点在于:

  1. 主机拉低必须超过18ms(实测20ms最稳)
  2. 释放总线后要等待20-40us再检测响应
  3. 从机响应信号是80us低电平+80us高电平

数据读取部分要注意采样窗口的把握。我最初用while循环等待上升沿,结果发现会卡死。后来改成超时检测才稳定:

unsigned char DHT11_rec_byte() { unsigned char i, dat = 0; for(i=0; i<8; i++) { while(!Temp_data && timeout++ < 100); // 超时保护 DHT11_delay_us(8); dat <<= 1; if(Temp_data) dat |= 1; while(Temp_data && timeout++ < 100); } return dat; }

校验机制是保证数据可靠性的关键。DHT11会发送5个字节,前4字节是温湿度数据,第5字节是校验和。校验方法很简单:

if((R_H + R_L + T_H + T_L) == revise) { // 校验通过才更新数据 rec_dat[0] = R_H; // 湿度整数 rec_dat[1] = R_L; // 湿度小数 rec_dat[2] = T_H; // 温度整数 rec_dat[3] = T_L; // 温度小数 }

3. LCD1602显示驱动详解

LCD1602的驱动让我又爱又恨——显示直观但调试麻烦。最头疼的是初始化顺序,稍有不对就显示乱码。经过多次测试,这个初始化序列最可靠:

void InitLcd1602() { Lcd1602_Write_Cmd(0x38); // 8位模式,2行显示 Lcd1602_Write_Cmd(0x0C); // 开显示,关光标 Lcd1602_Write_Cmd(0x06); // 地址递增,不移屏 Lcd1602_Write_Cmd(0x01); // 清屏 DHT11_delay_ms(2); // 必须延时! }

显示温湿度数据时,sprintf函数帮了大忙。它能把数值转换成字符串,还能控制小数位数:

sprintf(rec_dat_lcd0, "%d", rec_dat[0]); // 湿度整数 sprintf(rec_dat_lcd1, "%d", rec_dat[1]); // 湿度小数 LcdShowStr(7, 0, rec_dat_lcd0); LcdShowStr(9, 0, "."); LcdShowStr(10, 0, rec_dat_lcd1);

实际使用中发现LCD在低温环境下会反应迟钝。后来查到是液晶响应速度受温度影响,解决方法是在初始化前增加500ms延时,或者用加热膜保持屏温。

4. 串口通信与双显示方案

串口配置有个坑:STC89C52的定时器1必须工作在模式2(8位自动重装),否则波特率不准。这是我调试出的最佳配置:

void InitUART() { TMOD = 0x20; // 定时器1模式2 SCON = 0x50; // 串口模式1,允许接收 TH1 = 0xFD; // 9600波特率@11.0592MHz TL1 = 0xFD; TR1 = 1; // 启动定时器 TI = 1; // 必须置1才能用printf }

双显示的最大优势是调试信息互补。LCD显示当前值,串口记录历史曲线。我用下面的格式输出,方便后期用Excel分析:

printf("Humi:%d.%d%%\tTemp:%d.%dC\n", rec_dat[0], rec_dat[1], rec_dat[2], rec_dat[3]);

遇到数据跳动问题时,双显示立刻显出威力——通过对比发现是电源干扰导致。后来在传感器电源脚加了0.1uF去耦电容,问题迎刃而解。

5. 常见问题排查指南

问题1:DHT11无响应

  • 检查接线是否正确(VCC、GND、DATA)
  • 确认DATA引脚接了上拉电阻
  • 测量电源电压是否在3.3-5.5V范围
  • 尝试降低通信速率,增加延时

问题2:LCD显示乱码

  • 重新插拔16P排线,确保接触良好
  • 调节VO引脚电位器改变对比度
  • 检查初始化时序是否完整
  • 更换质量更好的LCD1602模块

问题3:串口数据异常

  • 核对波特率是否匹配(9600/115200)
  • 检查TX/RX线是否接反
  • 确认USB转TTL模块驱动已安装
  • 尝试降低通信波特率测试

有个隐蔽的坑是电源干扰。当开发板同时驱动LCD和DHT11时,电压波动会导致传感器复位。解决方法是在DHT11的VCC和GND之间并联100uF电解电容。

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

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

立即咨询