【花雕学编程】Arduino动手做(245)--DS3231模块12个小实验

2025-05-106901
AI 快速预览详细 收起
本文介绍了12个使用DS3231高精度时钟模块的Arduino实验。每个实验都详细记录了连接方式、代码和结果。这些实验适合零基础新手,帮助他们逐步掌握IIC/I2C接口的实时计时传感器。通过这些实验,用户可以了解如何连接和配置DS3231模块,并解决常见的连接问题。


37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题,希望能够抛砖引玉。

【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百四十五:DS3231 高精度时钟模块  IIC/I2C接口 实时计时传感器


【花雕学编程】Arduino动手做(245)--DS3231模块12个小实验图1


创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(56)
驴友花雕
驴友花雕
作者
电原理图

驴友花雕
驴友花雕
作者
实验场景图


驴友花雕
驴友花雕
作者
实验串口返回情况

驴友花雕
驴友花雕
作者
代码简单解读
这段代码使用 DS3231 实时时钟(RTC) 和 LCD 显示屏 通过 I2C 通信 显示当前时间和日期,核心逻辑如下:
1. 初始化硬件
✅ Wire.begin(); → 启动 I2C 通信
✅ rtc.begin(); → 初始化 DS3231 RTC
✅ lcd.init(); → 初始化 LCD 显示屏
✅ lcd.backlight(); → 开启 LCD 背光
2. 设置 RTC 时间
✅ rtc.lostPower(); → 如果 RTC 断电,则恢复默认时间
✅ rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); → 自动设置 RTC 时间为编译时的系统时间
3. 获取当前时间
✅ rtc.now(); → 从 RTC 获取当前时间
✅ 格式化时间为 "HH:MM:SS" 形式
✅ 格式化日期为 "YYYY-MM-DD" 形式
4. 显示内容在 LCD 屏幕上
✅ 时间 → lcd.print(dt.hour()); 等格式化
✅ 日期 → lcd.print(dt.year()); 等格式化
5. 采集间隔
✅ delay(500); → 每 500 毫秒更新一次时间
这段代码让 LCD 显示当前时间,并持续更新。
驴友花雕
驴友花雕
作者
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十二:在 LCD 上显示 RTC 模块的时间和日期
实验开源代码
[code]/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十二:在 LCD 上显示 RTC 模块的时间和日期
*/
#include
#include
#include
#define LCD_ADDRESS 0x27 // LCD I2C 地址
#define LCD_COLUMNS 16 // LCD 显示屏的列数
#define LCD_ROWS 2 // LCD 显示屏的行数
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS); // 创建 LCD 显示对象
RTC_DS3231 rtc; // 使用 Adafruit RTClib 创建 DS3231 RTC 实例
void setup() {
Serial.begin(9600); // 初始化串口通信
Wire.begin(); // 启动 I2C 通信
lcd.init(); // 初始化 LCD 显示屏
lcd.backlight(); // 开启 LCD 背光
lcd.clear(); // 清屏
// 初始化 RTC
if (!rtc.begin()) {
Serial.println("RTC 初始化失败!");
while (1); // 停止执行
}
// 如果 RTC 断电,则恢复默认时间
if (rtc.lostPower()) {
Serial.println("RTC 断电!正在设置时间...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
DateTime dt = rtc.now(); // 获取当前时间
// 显示时间
lcd.setCursor(4, 0);
lcd.print(dt.hour());
lcd.print(":");
lcd.print(dt.minute());
lcd.print(":");
lcd.print(dt.second());
// 显示日期
lcd.setCursor(3, 1);
lcd.print(dt.year());
lcd.print("-");
lcd.print(dt.month());
lcd.print("-");
lcd.print(dt.day());
// 串口输出时间
Serial.print("当前时间: ");
Serial.print(dt.year()); Serial.print("-");
Serial.print(dt.month()); Serial.print("-");
Serial.print(dt.day()); Serial.print(" ");
Serial.print(dt.hour()); Serial.print(":");
Serial.print(dt.minute()); Serial.print(":");
Serial.println(dt.second());
delay(500); // 每 500 毫秒更新一次
}[/code]
驴友花雕
驴友花雕
作者
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十二:在 LCD 上显示 RTC 模块的时间和日期
实验模块接线示意图


驴友花雕
驴友花雕
作者

驴友花雕
驴友花雕
作者

驴友花雕
驴友花雕
作者
实验场景图


驴友花雕
驴友花雕
作者
代码简单解读
这段代码使用 DS3231 实时时钟(RTC)模块 和 OLED 显示屏 通过 I2C 通信 显示 当前日期、时间、星期和温度,核心逻辑如下:
1. 初始化硬件
✅ Wire.begin(); → 启动 I2C 通信
✅ display.begin(...); → 初始化 OLED 显示屏(I2C 地址 0x3C)
✅ rtc.begin(); → 初始化 DS3231 RTC
2. 设置 RTC 时间
✅ rtc.lostPower(); → 如果 RTC 断电,则恢复默认时间
✅ rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); → 自动设置 RTC 时间为编译时的系统时间
3. 读取当前时间
✅ rtc.now(); → 从 RTC 获取当前时间
✅ 格式化时间为 "YYYY-MM-DD" 和 "HH:MM:SS" 形式
4. 显示内容在 OLED 屏幕上
✅ 日期 → display.print(now.year()); 等显示格式
✅ 时间 → display.print(now.hour()); 等格式化
✅ 星期 → display.print(daysOfTheWeek[now.dayOfTheWeek()]);
✅ 温度 → display.print(rtc.getTemperature());
5. 采集间隔
✅ delay(1000); → 每秒更新一次时间
这段代码让 OLED 显示当前时间,并持续更新。
驴友花雕
驴友花雕
作者
实验开源代码
[code]/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十一:OLED 显示日期、时间、星期和温度
*/
#include // **引入 I2C 通信库**
#include // **引入 DS3231 RTC 库**
#include // **引入 Adafruit SSD1306 OLED 显示库**
RTC_DS3231 rtc; // **创建 DS3231 RTC 对象**
#define SCREEN_WIDTH 128 // **OLED 屏幕宽度(单位:像素)**
#define SCREEN_HEIGHT 64 // **OLED 屏幕高度(单位:像素)**
// **创建 OLED 显示对象,使用 I2C 进行通信**
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// **定义星期数组**
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup() {
Serial.begin(9600); // **初始化串口通信**
// **初始化 OLED 显示屏**
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // **设置 I2C 地址为 0x3C**
Serial.println("SSD1306 显示屏初始化失败");
while (true); // **进入死循环,防止继续执行错误代码**
}
// **清除 OLED 屏幕并显示空白**
display.clearDisplay();
display.display();
// **初始化 DS3231 RTC 模块**
if (!rtc.begin()) {
Serial.println("找不到 RTC 模块");
while (true); // **进入死循环,避免继续执行错误代码**
}
// **如果 RTC 断电,自动设置时间**
if (rtc.lostPower()) {
Serial.println("RTC 断电!正在设置时间...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // **设置 RTC 时间为编译时系统时间**
}
// **如果需要手动设置时间,请取消注释以下代码**
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
void loop() {
// **从 RTC 获取当前时间**
DateTime now = rtc.now();
// **清除 OLED 显示缓冲区**
display.clearDisplay();
// **显示日期**
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Date: ");
display.print(now.year()); // **打印年份**
display.print("-");
if (now.month() < 10) display.print("0"); // **补零**
display.print(now.month()); // **打印月份**
display.print("-");
if (now.day() < 10) display.print("0"); // **补零**
display.print(now.day()); // **打印日期**
// **显示时间**
display.setCursor(0, 15);
display.print("Time: ");
if (now.hour() < 10) display.print("0"); // **补零**
display.print(now.hour()); // **打印小时**
display.print(":");
if (now.minute() < 10) display.print("0"); // **补零**
display.print(now.minute()); // **打印分钟**
display.print(":");
if (now.second() < 10) display.print("0"); // **补零**
display.print(now.second()); // **打印秒数**
// **显示星期**
display.setCursor(0, 30);
display.print("Day: ");
display.print(daysOfTheWeek[now.dayOfTheWeek()]); // **获取星期名称**
// **显示 DS3231 传感器温度**
display.setCursor(0, 45);
display.print("Temp: ");
display.print(rtc.getTemperature()); // **读取温度**
display.cp437(true);
display.write(167); // **显示摄氏度符号**
display.print("C");
// **刷新 OLED 显示**
display.display();
delay(1000); // **每秒更新数据**
}[/code]
驴友花雕
驴友花雕
作者
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十一:OLED 显示日期、时间、星期和温度
模块参考电原理图

驴友花雕
驴友花雕
作者
实验模块接线示意图

驴友花雕
驴友花雕
作者
实验场景图

驴友花雕
驴友花雕
作者
代码简单解读
这段代码使用 DS3231 实时时钟(RTC)模块 和 OLED 显示屏,通过 I2C 通信 实现 时间显示,核心逻辑如下:
1. 初始化硬件
✅ Wire.begin(); → 启动 I2C 通信
✅ oled.begin(...); → 初始化 OLED 显示屏(I2C 地址 0x3C)
✅ rtc.begin(); → 初始化 DS3231 RTC
2. 设置 RTC 时间
✅ rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); → 自动设置 RTC 时间为编译时的系统时间
✅ 确保 RTC 运行正确,否则进入死循环
3. 获取当前时间
✅ rtc.now(); → 从 RTC 读取当前时间
✅ 格式化为 "小时:分钟:秒" 形式 并存入 String time
4. 显示时间在 OLED 屏幕上
✅ oledDisplayCenter(time); → 将时间居中显示
✅ 计算文本大小,确保居中
✅ 清除屏幕并更新显示
5. 采集间隔
✅ 每秒刷新一次时间,保证实时性
这段代码让 OLED 显示当前时间,并不断更新。
驴友花雕
驴友花雕
作者
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上
实验开源代码
[code]/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上
*/
#include // **引入 I2C 通信库**
#include // **引入 Adafruit GFX 图形库**
#include // **引入 Adafruit SSD1306 OLED 显示库**
#include // **引入 DS3231 RTC 库**
#define SCREEN_WIDTH 128 // **OLED 屏幕宽度(单位:像素)**
#define SCREEN_HEIGHT 64 // **OLED 屏幕高度(单位:像素)**
// **创建 SSD1306 OLED 显示对象,使用 I2C 进行通信**
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// **创建 DS3231 RTC 对象**
RTC_DS3231 rtc;
// **用于存储时间字符串**
String time;
void setup() {
Serial.begin(9600); // **初始化串口通信**
// **初始化 OLED 显示屏**
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // **设置 I2C 地址为 0x3C**
Serial.println(F("SSD1306 显示屏初始化失败"));
while (true); // **进入死循环,防止继续执行错误代码**
}
delay(2000); // **等待 2 秒,确保 OLED 组件启动**
oled.clearDisplay(); // **清空 OLED 屏幕**
oled.setTextSize(1); // **设置文本大小**
oled.setTextColor(WHITE); // **设置文本颜色**
oled.setCursor(0, 10); // **设置文本显示位置**
// **初始化 DS3231 RTC 模块**
if (!rtc.begin()) {
Serial.println("找不到 RTC 模块");
Serial.flush();
while (true); // **进入死循环,避免继续执行错误代码**
}
// **同步 RTC 时间,设置为编译时的日期和时间**
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// **预留 10 个字节内存,优化 String 变量存储,避免碎片化**
time.reserve(10);
}
void loop() {
// **从 RTC 读取当前时间**
DateTime now = rtc.now();
time = ""; // **清空字符串**
time += now.hour(); // **获取小时**
time += ':';
time += now.minute(); // **获取分钟**
time += ':';
time += now.second(); // **获取秒数**
oledDisplayCenter(time); // **调用 OLED 显示函数**
}
/*****************************************************************************************************
* **oledDisplayCenter**
* - 计算文本大小,使其居中显示在 OLED 屏幕上
* - 然后将时间数据显示在屏幕中央
*****************************************************************************************************/
void oledDisplayCenter(String text) {
int16_t x1, y1;
uint16_t width, height;
// **获取文本的宽度和高度**
oled.getTextBounds(text, 0, 0, &x1, &y1, &width, &height);
// **清屏**
oled.clearDisplay();
// **计算居中位置**
oled.setCursor((SCREEN_WIDTH - width) / 2, (SCREEN_HEIGHT - height) / 2);
// **显示时间字符串**
oled.println(text);
oled.display(); // **刷新 OLED 屏幕**
}[/code]
驴友花雕
驴友花雕
作者
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上
安装RTClib.h库 (https://github.com/adafruit/RTClib

驴友花雕
驴友花雕
作者
实验串口返回情况

驴友花雕
驴友花雕
作者
代码简单解读
这段代码使用 DS3231 实时时钟(RTC)模块 通过 I2C 通信 读取当前时间、温度和闹钟状态,并在 串口监视器 输出,核心逻辑如下:
1. 初始化 RTC
✅ DS3231 myRTC; → 创建 DS3231 实例
✅ Wire.begin(); → 启动 I2C 通信
✅ Serial.begin(57600); → 初始化串口通信,波特率 57600
2. 读取时间数据
✅ myRTC.getYear(); → 获取年份
✅ myRTC.getMonth(); → 获取月份
✅ myRTC.getDate(); → 获取日期
✅ myRTC.getDoW(); → 获取星期
✅ myRTC.getHour(h12Flag, pmFlag); → 获取小时(支持 AM/PM 显示)
✅ myRTC.getMinute(); → 获取分钟
✅ myRTC.getSecond(); → 获取秒数
3. 读取温度数据
✅ myRTC.getTemperature(); → 获取 DS3231 内部温度传感器数据
4. 监测 RTC 运行状态
✅ myRTC.oscillatorCheck(); → 检查 RTC 振荡器是否正常工作
✅ myRTC.checkIfAlarm(1); → 检查 Alarm 1 是否触发
✅ myRTC.checkIfAlarm(2); → 检查 Alarm 2 是否触发
5. 读取闹钟设定
✅ myRTC.getA1Time(); → 获取 Alarm 1 的设定时间
✅ myRTC.getA2Time(); → 获取 Alarm 2 的设定时间
✅ myRTC.checkAlarmEnabled(1); → 检查 Alarm 1 是否启用
✅ myRTC.checkAlarmEnabled(2); → 检查 Alarm 2 是否启用
6. 采集间隔
✅ delay(1000); → 每秒更新一次数据
这段代码让 DS3231 RTC 模块不断读取时间、日期、温度和闹钟状态,并在串口监视器显示。
驴友花雕
驴友花雕
作者
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之九:读取当前时间、温度和闹钟状态
实验开源代码
[code]/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块 IIC/I2C接口 实时计时传感器
项目之九:读取当前时间、温度和闹钟状态
*/
#include // 引入DS3231时钟库
#include // 引入I2C通信库
DS3231 myRTC; // 创建DS3231对象
bool century = false; // 世纪标志位(20xx年为false,21xx年为true)
bool h12Flag; // 12小时制标志
bool pmFlag; // 下午标志(仅在12小时制下有效)
byte alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits; // 闹钟参数
bool alarmDy, alarmH12Flag, alarmPmFlag; // 闹钟日期/星期标志和12小时制标志
void setup() {
// 初始化I2C通信(SDA:A4, SCL:A5)
Wire.begin();
// 初始化串口通信,波特率57600
Serial.begin(57600);
}
void loop() {
// 向串口监视器发送当前时钟信息
// 显示年份(20xx格式)
Serial.print("2");
if (century) { // 21世纪(此标志在未来89年内不会用到)
Serial.print("1");
} else {
Serial.print("0");
}
Serial.print(myRTC.getYear(), DEC); // 显示年份后两位
Serial.print(' ');
// 显示月份
Serial.print(myRTC.getMonth(century), DEC);
Serial.print(" ");
// 显示日期
Serial.print(myRTC.getDate(), DEC);
Serial.print(" ");
// 显示星期(1-7对应周日到周六)
Serial.print(myRTC.getDoW(), DEC);
Serial.print(" ");
// 显示时分秒
Serial.print(myRTC.getHour(h12Flag, pmFlag), DEC);
Serial.print(" ");
Serial.print(myRTC.getMinute(), DEC);
Serial.print(" ");
Serial.print(myRTC.getSecond(), DEC);
// 添加AM/PM指示(仅在12小时制下有效)
if (h12Flag) {
if (pmFlag) {
Serial.print(" PM ");
} else {
Serial.print(" AM ");
}
} else {
Serial.print(" 24h "); // 24小时制显示
}
// 显示温度(DS3231内置高精度温度传感器)
Serial.print("T=");
Serial.print(myRTC.getTemperature(), 2); // 显示温度,保留两位小数
// 显示振荡器状态(O+表示正常,O-表示振荡器可能停止)
if (myRTC.oscillatorCheck()) {
Serial.print(" O+"); // 振荡器正常工作
} else {
Serial.print(" O-"); // 振荡器可能停止,时间可能不准确
}
// 显示闹钟触发状态
if (myRTC.checkIfAlarm(1)) {
Serial.print(" A1!"); // 闹钟1触发
}
if (myRTC.checkIfAlarm(2)) {
Serial.print(" A2!"); // 闹钟2触发
}
// 换行
Serial.println();
// 显示闹钟1设置信息
Serial.print("Alarm 1: ");
myRTC.getA1Time(alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits, alarmDy, alarmH12Flag, alarmPmFlag);
Serial.print(alarmDay, DEC);
if (alarmDy) {
Serial.print(" DoW"); // 按星期触发
} else {
Serial.print(" Date"); // 按日期触发
}
Serial.print(' ');
Serial.print(alarmHour, DEC);
Serial.print(' ');
Serial.print(alarmMinute, DEC);
Serial.print(' ');
Serial.print(alarmSecond, DEC);
Serial.print(' ');
if (alarmH12Flag) {
if (alarmPmFlag) {
Serial.print("pm ");
} else {
Serial.print("am ");
}
}
if (myRTC.checkAlarmEnabled(1)) {
Serial.print("enabled"); // 闹钟1已启用
}
Serial.println();
// 显示闹钟2设置信息
Serial.print("Alarm 2: ");
myRTC.getA2Time(alarmDay, alarmHour, alarmMinute, alarmBits, alarmDy, alarmH12Flag, alarmPmFlag);
Serial.print(alarmDay, DEC);
if (alarmDy) {
Serial.print(" DoW"); // 按星期触发
} else {
Serial.print(" Date"); // 按日期触发
}
Serial.print(" ");
Serial.print(alarmHour, DEC);
Serial.print(" ");
Serial.print(alarmMinute, DEC);
Serial.print(" ");
if (alarmH12Flag) {
if (alarmPmFlag) {
Serial.print("pm");
} else {
Serial.print("am");
}
}
if (myRTC.checkAlarmEnabled(2)) {
Serial.print("enabled"); // 闹钟2已启用
}
// 显示闹钟触发条件位(二进制格式)
Serial.println();
Serial.print("Alarm bits: ");
Serial.println(alarmBits, BIN);
// 空行分隔,每秒更新一次
Serial.println();
delay(1000);
} [/code]