亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Arduino 带日期时间 LCD 时钟:DS3231 RTC + I2C 接口 + 三键调校全攻略

项目定位

本项目在“极简时钟”基础上引入 **DS3231 高精度 RTC** 与 **I2C LCD1602**,实现掉电走时、自动闰年/闰月、三按钮菜单式调校(年/月/日/时/分/秒),适合作为数据记录仪、定时开关、智能家居节点的时间基准模块。

硬件清单

元件数量关键参数
Arduino UNO R31
I2C LCD1602(带 PCF8574 背包)1地址通常 0x27 或 0x3F
DS3231 RTC 模块(带 CR2032 电池座)1精度 ±2 ppm,-40~+85°C
12 mm 轻触按钮3菜单/加/减,接 D2/D3/D4
10 kΩ 电阻3按钮下拉(也可用内部上拉反向逻辑)
面包板 + 杜邦线1套

I2C 总线拓扑

Arduino UNO          DS3231          LCD1602(I2C)
   A4 (SDA)  ──────── SDA  ──────── SDA
   A5 (SCL)  ──────── SCL  ──────── SCL
   5V        ──────── VCC  ──────── VCC
   GND       ──────── GND  ──────── GND
// 两设备共享总线,只需各自地址不同即可

库依赖

核心代码逻辑

1. 初始化与首次授时

#include 
#include 
#include 

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);  // 地址按实测修改

const uint8_t BTN_MENU=2, BTN_UP=3, BTN_DOWN=4;
enum { VIEW, SET_YEAR, SET_MONTH, SET_DAY, SET_HOUR, SET_MIN, SET_SEC } mode = VIEW;
DateTime now;

void setup() {
  pinMode(BTN_MENU, INPUT_PULLUP);
  pinMode(BTN_UP, INPUT_PULLUP);
  pinMode(BTN_DOWN, INPUT_PULLUP);
  lcd.init(); lcd.backlight();
  if (!rtc.begin()) { lcd.print(F("RTC FAIL")); while(1); }
  if (rtc.lostPower()) {                // 首次上电或电池耗尽
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  // 编译时刻写入
  }
}

2. 非阻塞主循环 + 状态机菜单


void loop() {
  now = rtc.now();
  static uint32_t lastDraw = 0;
  if (millis() - lastDraw >= 500) { lastDraw = millis(); drawView(); }
  handleMenu();
}

void drawView() {
  char buf[17];
  sprintf(buf, "%04d/%02d/%02d", now.year(), now.month(), now.day());
  lcd.setCursor(0,0); lcd.print(buf);
  sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  lcd.setCursor(0,1); lcd.print(buf);
}

void handleMenu() {
  static uint32_t lastBtn = 0;
  if (millis() - lastBtn < 150) return;  // 简单去抖
  if (digitalRead(BTN_MENU) == LOW) {
    lastBtn = millis();
    mode = (mode + 1) % 7;               // 循环切换设置项
    lcd.setCursor(0,1); lcd.print(F("SET: "));
    lcd.print(modeNames[mode]);
  }
  if (mode != VIEW) {
    if (digitalRead(BTN_UP) == LOW) { adjust(+1); lastBtn = millis(); }
    if (digitalRead(BTN_DOWN) == LOW) { adjust(-1); lastBtn = millis(); }
  }
}

void adjust(int8_t delta) {
  DateTime t = now;
  switch(mode) {
    case SET_YEAR:  t = DateTime(t.year()+delta, t.month(), t.day(), t.hour(), t.minute(), t.second()); break;
    case SET_MONTH: t = DateTime(t.year(), constrain(t.month()+delta,1,12), t.day(), t.hour(), t.minute(), t.second()); break;
    case SET_DAY:   t = DateTime(t.year(), t.month(), constrain(t.day()+delta,1,31), t.hour(), t.minute(), t.second()); break;
    case SET_HOUR:  t = DateTime(t.year(), t.month(), t.day(), (t.hour()+delta+24)%24, t.minute(), t.second()); break;
    case SET_MIN:   t = DateTime(t.year(), t.month(), t.day(), t.hour(), (t.minute()+delta+60)%60, t.second()); break;
    case SET_SEC:   t = DateTime(t.year(), t.month(), t.day(), t.hour(), t.minute(), (t.second()+delta+60)%60); break;
  }
  rtc.adjust(t);  // 立即写入 RTC
  now = t;        // 同步本地变量,避免读取延迟
}

进阶功能与避坑指南

  1. DS3231 温度补偿:芯片内置 TCXO,无需外部晶振,年误差 < 1 分钟。
  2. I2C 地址冲突:LCD 常见 0x27/0x3F,DS3231 固定 0x68。用 I2C_scanner 例程确认。
  3. 按钮下拉 vs 上拉:原文用外部 10k 下拉(按下=HIGH),代码示例改用 INPUT_PULLUP(按下=LOW),硬件只需按钮一脚接 GND,省去电阻。
  4. 闰年/月天数:DateTime 构造函数自动校验,非法日期会自动修正(如 2 月 30 日 → 3 月 2 日)。
  5. 备用电池:CR2032 典型续航 3~5 年,建议每两年测量电压(>2.9 V 正常)。

扩展应用场景


总结:DS3231 + I2C LCD + 三键菜单,构建一个“上电即用、掉电不停、随时可调”的工业级时间显示模块,代码量 < 100 行,极适合二次集成。

制造工艺

  1. 复古 Numitron 管时钟:Arduino Nano 驱动,低温可靠省电
  2. 精准文字时钟:分钟级文字显示时间
  3. Arduino Due 驱动 3.2″ TFT 实现温度监测与实时时钟
  4. 用 Arduino UNO 制作柏林时钟 – DIY LED 矩阵时钟
  5. 3D 打印月相时钟:Arduino Nano 驱动 OLED+NeoPixel 还原真实月相
  6. 用 DS1302 RTC 和 Arduino UNO 制作可靠闹钟
  7. C++日期时间完全指南:ctime库、tm结构体与格式化输出
  8. Python 获取当前日期和时间:实用指南
  9. Python 日期时间处理实战:time 与 calendar 模块完全指南
  10. 掌握 Java 日期时间:构造器、方法与最佳实践
  11. Java 8 全新日期时间 API:线程安全、设计优雅、时区处理轻松搞定
  12. 确保新疫苗与生物制剂及时生产