基于Arduino Uno的无RTC数字时钟开发:DHT11温湿度轮显需求
Arduino Uno 无RTC数字时钟+DHT11温湿度切换显示方案
嘿,这个实用的小项目挺有意思的!我给你整理了一套完整的实现方案,分硬件、代码、关键细节三部分,跟着做就能轻松搞定~
整体思路
因为不用RTC模块,我们用Arduino的millis()函数实现非阻塞式计时(避免delay()导致的程序卡顿);LCD1602第一行固定显示时间,第二行通过定时器控制,每2秒切换一次温度和湿度显示;DHT11负责读取温湿度数据,同时加入错误处理避免读取失败时的乱码。
硬件接线说明
推荐用I2C版本的LCD1602,接线更简洁:
- LCD1602(I2C):
- VCC → Arduino Uno 5V引脚
- GND → Arduino Uno GND引脚
- SDA → Arduino Uno A4引脚
- SCL → Arduino Uno A5引脚
- DHT11传感器:
- VCC → Arduino Uno 5V引脚
- GND → Arduino Uno GND引脚
- DATA → Arduino Uno D2引脚(代码里可修改对应引脚)
- 补充:如果你的DHT11模块没有自带上拉电阻,需要在DATA和VCC之间接一个10KΩ的电阻,保证信号稳定。
完整代码实现
先确保你已经在Arduino库管理器里安装了LiquidCrystal_I2C和DHT库:
#include <LiquidCrystal_I2C.h> #include <DHT.h> // 初始化I2C LCD(地址通常为0x27或0x3F,根据你的模块调整) LiquidCrystal_I2C lcd(0x27, 16, 2); // 初始化DHT11 #define DHTPIN 2 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); // 计时相关变量 unsigned long lastTimeUpdate = 0; const long timeInterval = 1000; // 1秒更新一次时间 int seconds = 0; int minutes = 0; int hours = 12; // 初始时间,可自行修改 // 温湿度切换相关变量 unsigned long lastDisplaySwitch = 0; const long displayInterval = 2000; // 2秒切换一次显示 bool showTemperature = true; // 当前显示状态:true=温度,false=湿度 float tempValue = 0.0; float humiValue = 0.0; void setup() { lcd.init(); lcd.backlight(); // 打开LCD背光 dht.begin(); Serial.begin(9600); // 串口调试用,不需要可注释掉 } void loop() { unsigned long currentMillis = millis(); // --- 处理时间更新 --- if (currentMillis - lastTimeUpdate >= timeInterval) { lastTimeUpdate = currentMillis; seconds++; // 时间进位逻辑 if (seconds >= 60) { seconds = 0; minutes++; if (minutes >= 60) { minutes = 0; hours++; if (hours >= 24) hours = 0; } } // 更新第一行时间显示(格式化补零) lcd.setCursor(0, 0); lcd.print("TIME:"); if (hours < 10) lcd.print("0"); lcd.print(hours); lcd.print(":"); if (minutes < 10) lcd.print("0"); lcd.print(minutes); lcd.print(":"); if (seconds < 10) lcd.print("0"); lcd.print(seconds); } // --- 处理温湿度切换与读取 --- if (currentMillis - lastDisplaySwitch >= displayInterval) { lastDisplaySwitch = currentMillis; // 切换前先清空第二行(用空格覆盖,避免残留字符) lcd.setCursor(0, 1); lcd.print(" "); // 16个空格刚好填满一行 // 切换显示状态 showTemperature = !showTemperature; // 读取温湿度数据 humiValue = dht.readHumidity(); tempValue = dht.readTemperature(); // 检查读取是否成功 if (isnan(humiValue) || isnan(tempValue)) { lcd.setCursor(0, 1); lcd.print("Sensor Error!"); return; } } // --- 显示当前温湿度 --- lcd.setCursor(0, 1); if (showTemperature) { lcd.print("TEMP(℃):"); lcd.print(tempValue, 2); // 显示两位小数 } else { lcd.print("HUM(%):"); lcd.print(humiValue, 2); } }
关键细节说明
- 非阻塞计时的重要性:用
millis()代替delay(),这样计时、温湿度读取、LCD切换可以同时进行,不会出现程序卡顿的情况。如果用delay(),切换温湿度时时间会停止走,体验很差。 - LCD清行技巧:不用
lcd.clear()(会清空整个屏幕),而是用16个空格覆盖第二行,保证第一行的时间持续显示。 - DHT11错误处理:加入
isnan()判断传感器读取是否成功,如果失败就显示错误信息,避免出现乱码。 - 初始时间设置:因为没有RTC,每次上电后时间从代码里的
hours、minutes、seconds初始值开始,你可以根据需要修改这些值。 - LCD I2C地址排查:如果LCD不显示内容,可能是地址不对。可以用I2C扫描程序确认地址,然后修改代码里的
LiquidCrystal_I2C lcd(0x27, 16, 2);中的地址(常见地址是0x27或0x3F)。
如果调试时遇到问题,可以打开串口监视器,看看温湿度的读取值是否正常,时间更新是否准确。祝你项目顺利!
内容的提问来源于stack exchange,提问作者user9081078
相关产品推荐
相关产品推荐

