【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之四:计算 从 1970 年 1 月 1 日午夜以来的时间(Unix 时间戳)
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之四:计算 从 1970 年 1 月 1 日午夜以来的时间(Unix 时间戳)
*/
#include <Wire.h>
#include <DS3231.h>
RTClib myRTC;
void setup () {
Serial.begin(57600);
Wire.begin();
delay(500);
Serial.println("Nano Ready!");
}
void loop () {
delay(2000);
DateTime now = myRTC.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.print(" 自1970年1月1日午夜以来 = ");
Serial.print(now.unixtime());
Serial.print("秒 = ");
Serial.print(now.unixtime() / 86400L);
Serial.println(" 天");
}
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
代码解读这段代码使用 DS3231 实时时钟(RTC)模块 获取 当前时间和日期,并计算 从 1970 年 1 月 1 日午夜以来的时间(Unix 时间戳),核心逻辑如下:
1. 引入库
✅ #include <Wire.h> → 用于 I2C 通信 ✅ #include <DS3231.h> → 用于 DS3231 RTC 控制 ✅ RTClib myRTC; → 创建 RTC 对象,用于管理时间数据
2. 初始化
✅ Serial.begin(57600); → 设置串口通信速率为 57600 ✅ Wire.begin(); → 初始化 I2C 通信 ✅ Serial.println("Nano Ready!"); → 打印启动消息 ✅ delay(500); → 等待 500 毫秒,确保 RTC 启动
3. 读取并显示时间
✅ DateTime now = myRTC.now(); → 获取当前时间 ✅ Serial.print(now.year(), DEC); → 显示年份 ✅ Serial.print(now.month(), DEC); → 显示月份 ✅ Serial.print(now.day(), DEC); → 显示日期 ✅ Serial.print(now.hour(), DEC); → 显示小时 ✅ Serial.print(now.minute(), DEC); → 显示分钟 ✅ Serial.print(now.second(), DEC); → 显示秒
4. 计算 Unix 时间
✅ Serial.print(now.unixtime()); → 获取 Unix 时间戳(秒数) ✅ Serial.print(now.unixtime() / 86400L); → 计算从 1970 年 1 月 1 日以来的天数
5. 采集间隔
✅ delay(2000); → 每 2 秒更新一次数据
这段代码让 DS3231 RTC 模块不断读取时间,并计算 Unix 时间戳。
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
实验串口返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之五:生成 9 单位的矩形波
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之五:生成 9 单位的矩形波
*/
#include <Wire.h>
#include <DS3231.h>
DS3231 rtc;// 创建 DS3231 RTC 实例
void setup() {
Serial.begin(9600);// 初始化串口通信
Wire.begin();// 初始化 I2C 通信
}
void loop() {
rtc.getTemperature();// 刷新 RTC 数据
int second = rtc.getSecond();// 获取当前秒数
int signal = (second % 2 == 0) ? 9 : 0;// 每秒切换 0 和 9,生成矩形波
Serial.println(signal);// 发送数据到串口绘图器
delay(100);// 确保绘图器稳定显示波形
}
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
代码解读这段代码使用 DS3231 实时时钟(RTC)模块 通过 I2C 通信 获取 当前秒数,并在串口绘图器生成矩形波,核心逻辑如下:
1. 初始化 RTC
✅ DS3231 rtc; → 创建 DS3231 实例(使用默认 I2C 地址)
✅ Wire.begin(); → 启动 I2C 通信
✅ Serial.begin(9600); → 初始化串口通信
2. 读取秒数据
✅ rtc.getSecond(); → 获取当前秒数
✅ second % 2 == 0 ? 9 : 0; → 偶数秒输出 9,奇数秒输出 0,形成矩形波
3. 发送数据
✅ Serial.println(signal); → 将数据发送至串口绘图器,用于实时显示波形
4. 采集间隔
✅ delay(100); → 每 100 毫秒更新一次数据,确保波形稳定
这段代码让 DS3231 模块精准控制矩形波,并在串口绘图器显示。
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
实验串口返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
实验串口绘图器返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之六:通过串口监视器输出报警状态
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之六:通过串口监视器输出报警状态
*/
#include <DS3231.h>// 引入 DS3231 实时时钟库
#include <Wire.h> // 引入 I2C 通信库
// **创建 DS3231 RTC 对象**
DS3231 myRTC;
void setup() {
// **初始化 I2C 通信**
Wire.begin();
// **初始化串口通信,波特率为 57600**
Serial.begin(57600);
// **设置 "报警1",每分钟触发**
// 关闭 Alarm1,不需要手动打开
myRTC.turnOffAlarm(1);
myRTC.setA1Time(0, 0, 0, 0, 0b01111110, false, false, false);
myRTC.checkIfAlarm(1);
// **设置 "报警2",每分钟触发**
// 关闭 Alarm2,不需要手动打开
myRTC.turnOffAlarm(2);
myRTC.setA2Time(0, 0, 0, 0b01111110, false, false, false);
myRTC.checkIfAlarm(2);
}
void loop() {
// **初始化 AlarmBits(报警状态位)**
byte AlarmBits = 0x0;
Serial.print("初始化 AlarmBits: ");
Serial.println(AlarmBits, BIN);// 以二进制格式打印
// **初始化时间变量**
byte ADay, AHour, AMinute, ASecond;
bool ADy, Ah12, APM;
// **获取 "报警1" 时间(不清除报警标志)**
myRTC.getA1Time(ADay, AHour, AMinute, ASecond, AlarmBits, ADy, Ah12, APM);
Serial.print("获取 A1 时间: ");
Serial.println(AlarmBits, BIN);// 预期值:0x(0000)1110
// **获取 "报警2" 时间(不清除报警标志)**
myRTC.getA2Time(ADay, AHour, AMinute, AlarmBits, ADy, Ah12, APM);
Serial.print("获取 A2 时间: ");
Serial.println(AlarmBits, BIN);// 预期值:0x01111110
// **获取 "报警1" 时间(清除报警标志)**
myRTC.getA1Time(ADay, AHour, AMinute, ASecond, AlarmBits, ADy, Ah12, APM, true);
Serial.print("清除后获取 A1 时间: ");
Serial.println(AlarmBits, BIN);// 预期值:0x(0000)1110
// **获取 "报警2" 时间(清除报警标志)**
myRTC.getA2Time(ADay, AHour, AMinute, AlarmBits, ADy, Ah12, APM, true);
Serial.print("清除后获取 A2 时间: ");
Serial.println(AlarmBits, BIN);// 预期值:0x01110000
delay(5000);// **每 5 秒更新一次数据**
}
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
代码解读这段代码使用 DS3231 实时时钟(RTC)模块 管理 报警系统,并通过 串口监视器输出报警状态,核心逻辑如下:
1. 初始化 RTC
✅ DS3231 myRTC; → 创建 DS3231 RTC 实例
✅ Wire.begin(); → 启动 I2C 通信
✅ Serial.begin(57600); → 设置串口波特率为 57600
2. 设置报警
✅ turnOffAlarm(1); → 关闭 Alarm1
✅ setA1Time(0, 0, 0, 0, 0b01111110, false, false, false); → 设置 Alarm1,每分钟触发
✅ turnOffAlarm(2); → 关闭 Alarm2
✅ setA2Time(0, 0, 0, 0b01111110, false, false, false); → 设置 Alarm2,每分钟触发
3. 读取报警状态
✅ getA1Time() → 获取 Alarm1 的时间数据
✅ getA2Time() → 获取 Alarm2 的时间数据
✅ Serial.println(AlarmBits, BIN); → 以二进制格式显示报警状态
4. 采集间隔
✅ delay(5000); → 每 5 秒更新一次数据
这段代码让 DS3231 模块管理报警,并在串口监视器查看报警状态。
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
实验串口返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之七:通过 Unix 时间戳设置 DS3231 时间
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之七:通过 Unix 时间戳设置 DS3231 时间
*/
#include <Wire.h>// 引入 I2C 通信库
#include <DS3231.h>// 引入 DS3231 RTC 库
// **格式化时间并输出**
void showTimeFormated(time_t t) {
#if defined (__AVR__)// 如果是 AVR 平台,调整时间戳
t -= 946684800UL;// 修正 Unix 时间(基于 2000 年)
#endif
char buffer;// 创建存储格式化时间的字符数组
struct tm *ptm;
ptm = gmtime(&t);// 将时间转换为 UTC 时间结构
const char *timeformat = "%a %F %X - weekday %w; CW %W";// 时间格式
strftime(buffer, sizeof(buffer), timeformat, ptm);// 格式化时间
Serial.print(buffer);
Serial.print("\n");
}
// **Unix 时间戳(1660644000 对应 2022-08-16 10:00:00 UTC)**
constexpr time_t tstmp {1660644000UL};
// **创建 RTC 实例**
RTClib myRTC;
DS3231 Clock;
void setup() {
Serial.begin(115200);// 初始化串口通信,波特率 115200
Wire.begin();// 启动 I2C 通信
delay(500);// 确保 RTC 启动稳定
Serial.println("\n\n\n测试 DS3231 - setEpoch()\n\n\n");
#if defined (__AVR__)
Serial.println("AVR 微控制器就绪!");
Wire.begin();
//#elif defined (ESP8266)
//Serial.println("ESP8266 微控制器就绪!");
//Wire.begin(0U, 2U);// 设置 ESP8266 的 I2C 连接:SDA = GPIO0,SCL = GPIO2
#endif
// **设置 DS3231 的时间**
Serial.println("设置 DS3231 的时间为:2022-08-16 10:00:00 (UTC)");
Serial.println("Unix 时间戳 - 1660644000");
Clock.setEpoch(tstmp, false);// 通过 Unix 时间戳设置 DS3231 时间
Clock.setClockMode(false);// 设定为 24 小时制
// **验证 DS3231 数据**
bool century = false;
bool h12Flag;
bool pmFlag;
DateTime now = myRTC.now();// 获取当前 RTC 时间
Serial.print("\n\n");
Serial.print(" DS3231 的当前时间: ");
Serial.print(Clock.getYear(), DEC);
Serial.print("-");
Serial.print(Clock.getMonth(century), DEC);
Serial.print("-");
Serial.print(Clock.getDate(), DEC);
Serial.print(" ");
Serial.print(Clock.getHour(h12Flag, pmFlag), DEC);
Serial.print(":");
Serial.print(Clock.getMinute(), DEC);
Serial.print(":");
Serial.print(Clock.getSecond(), DEC);
Serial.print("-星期 ");
Serial.print(Clock.getDoW(), DEC);
Serial.println();
Serial.print("\n\n");
Serial.print(" RTC 当前时间: ");
Serial.print(now.year(), DEC);
Serial.print("-");
Serial.print(now.month(), DEC);
Serial.print("-");
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(":");
Serial.print(now.minute(), DEC);
Serial.print(":");
Serial.print(now.second(), DEC);
Serial.println();
Serial.print("\n\n **格式化 Struct tm 输出:");
showTimeFormated(tstmp);// 以格式化方式输出时间
}
void loop() {
// 该代码仅在 setup() 运行一次,因此 loop() 不执行任何操作
}
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
代码简单解读这段代码使用 DS3231 实时时钟(RTC)模块 通过 I2C 通信 设置并读取时间,核心逻辑如下:
1. 初始化 RTC
✅ DS3231 Clock; → 创建 DS3231 RTC 对象
✅ Wire.begin(); → 启动 I2C 通信
✅ Serial.begin(115200); → 初始化串口通信,波特率 115200
2. 设置时间
✅ Clock.setEpoch(tstmp, false); → 使用 Unix 时间戳设置 DS3231 时间
✅ Clock.setClockMode(false); → 设定为 24 小时制
3. 读取并打印时间
✅ Clock.getYear(), Clock.getMonth(century), Clock.getDate(); → 获取年月日
✅ Clock.getHour(h12Flag, pmFlag), Clock.getMinute(), Clock.getSecond(); → 获取小时、分钟、秒
✅ Clock.getDoW(); → 获取星期
4. 格式化时间
✅ showTimeFormated(tstmp); → 格式化时间并打印
5. 采集间隔
✅ loop() 为空 → 代码只在 setup() 运行一次,不循环执行
这段代码让 DS3231 模块精准管理时间,并格式化输出到串口。
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
实验串口返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之八:通过 I2C 通信 接收用户输入的时间数据并更新时钟
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之八:通过 I2C 通信 接收用户输入的时间数据并更新时钟
*/
#include <DS3231.h>// 引入 DS3231 RTC 库
#include <Wire.h> // 引入 I2C 通信库
// **创建 DS3231 RTC 对象**
DS3231 myRTC;
// **定义时间变量**
byte year, month, date, dow;// 年、月、日、星期
byte hour, minute, second; // 时、分、秒
bool century = false;// 用于跨世纪判断
bool h12Flag; // 12 小时制标志
bool pmFlag; // PM 标志(仅用于 12 小时制)
/*****************************************************************************************************
* **初始化**
*- 开启串口和 I2C 通信
*- 解释程序的使用方法
*****************************************************************************************************/
void setup() {
Serial.begin(57600);// **初始化串口,波特率 57600**
Wire.begin();// **启动 I2C 通信**
// **等待 4 秒,确保 RTC 启动稳定**
delay(4000);
// **向用户解释时间格式**
Serial.println("时间格式:YYMMDDwhhmmssx");
Serial.println("其中:");
Serial.println("YY = 年(如 20 表示 2020 年)");
Serial.println("MM = 月(如 04 表示 4 月)");
Serial.println("DD = 日期(如 09 表示 9 号)");
Serial.println("w= 星期(1-7,1=星期天,5=星期四)");
Serial.println("hh = 24 小时制小时数(如 09 表示上午 9 点,21 表示晚上 9 点)");
Serial.println("mm = 分钟(如 02)");
Serial.println("ss = 秒(如 42)");
Serial.println("例如输入:2004095090242x");
Serial.println("-----------------------------------------------------------------------------");
Serial.println("请在串口输入时间,并以 'x' 结尾以设置 DS3231 的时间:");
}
/*****************************************************************************************************
* **主循环**
*- 监听串口输入的时间校正数据
*- 根据输入设置 DS3231 的时钟
*- 在 5 秒内回显 DS3231 时间
*****************************************************************************************************/
void loop() {
// **如果串口收到输入数据,则进行时间校正**
if (Serial.available()) {
inputDateFromSerial();// 读取串口数据并解析时间
myRTC.setClockMode(false);// **设置 24 小时模式**
// **将输入的时间写入 DS3231**
myRTC.setYear(year);
myRTC.setMonth(month);
myRTC.setDate(date);
myRTC.setDoW(dow);
myRTC.setHour(hour);
myRTC.setMinute(minute);
myRTC.setSecond(second);
// **连续 5 秒,每秒打印 DS3231 当前时间**
for (uint8_t i = 0; i < 5; i++) {
delay(1000);
Serial.print(myRTC.getYear(), DEC);
Serial.print("-");
Serial.print(myRTC.getMonth(century), DEC);
Serial.print("-");
Serial.print(myRTC.getDate(), DEC);
Serial.print(" ");
Serial.print(myRTC.getHour(h12Flag, pmFlag), DEC);// 24 小时制
Serial.print(":");
Serial.print(myRTC.getMinute(), DEC);
Serial.print(":");
Serial.println(myRTC.getSecond(), DEC);
}
// **提示用户输入新时间**
Serial.println("请在串口输入新的时间,并以 'x' 结尾以设置 DS3231:");
}
delay(1000);// 每秒刷新一次
}
/*****************************************************************************************************
* **inputDateFromSerial**
*- 读取用户串口输入的时间数据
*- 解析并存储到全局变量
*****************************************************************************************************/
void inputDateFromSerial() {
// **检查串口数据是否完整(结束字符为 'x')**
boolean isStrComplete = false;
char inputChar;
byte temp1, temp2;
char inputStr;// 存储输入的时间字符串
uint8_t currentPos = 0;
while (!isStrComplete) {
if (Serial.available()) {
inputChar = Serial.read();
inputStr = inputChar;
currentPos += 1;
// **检查输入是否以 'x' 结尾**
if (inputChar == 'x') {
isStrComplete = true;
}
}
}
Serial.println(inputStr);// **打印用户输入的数据**
// **查找字符串中的 'x' 位置**
int posX = -1;
for (uint8_t i = 0; i < 20; i++) {
if (inputStr == 'x') {
posX = i;
break;
}
}
// **ASCII 码 '0' 的值(用于转换字符为数字)**
uint8_t zeroAscii = '0';
// **解析年**
temp1 = (byte)inputStr - zeroAscii;
temp2 = (byte)inputStr - zeroAscii;
year = temp1 * 10 + temp2;
// **解析月**
temp1 = (byte)inputStr - zeroAscii;
temp2 = (byte)inputStr - zeroAscii;
month = temp1 * 10 + temp2;
// **解析日期**
temp1 = (byte)inputStr - zeroAscii;
temp2 = (byte)inputStr - zeroAscii;
date = temp1 * 10 + temp2;
// **解析星期**
dow = (byte)inputStr - zeroAscii;
// **解析小时**
temp1 = (byte)inputStr - zeroAscii;
temp2 = (byte)inputStr - zeroAscii;
hour = temp1 * 10 + temp2;
// **解析分钟**
temp1 = (byte)inputStr - zeroAscii;
temp2 = (byte)inputStr - zeroAscii;
minute = temp1 * 10 + temp2;
// **解析秒**
temp1 = (byte)inputStr - zeroAscii;
temp2 = (byte)inputStr - zeroAscii;
second = temp1 * 10 + temp2;
}
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
代码简单解读这段代码使用 DS3231 RTC(实时时钟)模块 通过 I2C 通信 接收用户输入的时间数据,并更新 DS3231 的时钟,核心逻辑如下:
1. 初始化 RTC
✅ DS3231 myRTC; → 创建 DS3231 RTC 对象
✅ Wire.begin(); → 启动 I2C 通信
✅ Serial.begin(57600); → 初始化串口,波特率 57600
2. 解释时间格式
✅ Serial.println() → 向用户展示输入格式(YYMMDDwhhmmssx)
✅ 示例输入 → "2004095090242x" 代表 2020 年 4 月 9 日星期四 09:02:42
3. 监听串口输入并解析时间
✅ inputDateFromSerial(); → 读取串口输入数据并转换为 RTC 兼容格式
✅ 解析年、月、日、星期、时、分、秒
✅ myRTC.setClockMode(false); → 设置为 24 小时制
✅ myRTC.setYear(year); → 设置年份
✅ myRTC.setMonth(month); → 设置月份
✅ myRTC.setDate(date); → 设置日期
✅ myRTC.setDoW(dow); → 设置星期
✅ myRTC.setHour(hour); → 设置小时
✅ myRTC.setMinute(minute); → 设置分钟
✅ myRTC.setSecond(second); → 设置秒
4. 每 5 秒回显当前时间
✅ 每秒打印 DS3231 当前时间,以确保时间正确
5. 采集间隔
✅ delay(1000); → 每秒监听串口输入,等待新时间数据
这段代码让 用户通过串口输入时间,并更新 DS3231 的时钟。
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
实验串口返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之九:读取当前时间、温度和闹钟状态
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之九:读取当前时间、温度和闹钟状态
*/
#include <DS3231.h>// 引入DS3231时钟库
#include <Wire.h> // 引入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);
}
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
代码简单解读这段代码使用 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动手做(245)--DS3231高精度时钟模块
实验串口返回情况【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上
安装RTClib.h库 (https://github.com/adafruit/RTClib)
【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上
实验开源代码
/*
【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上
*/
#include <Wire.h> // **引入 I2C 通信库**
#include <Adafruit_GFX.h> // **引入 Adafruit GFX 图形库**
#include <Adafruit_SSD1306.h> // **引入 Adafruit SSD1306 OLED 显示库**
#include <RTClib.h> // **引入 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 屏幕**
}