驴友花雕 发表于 2025-5-11 10:17:36

【花雕学编程】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(" 天");
}

驴友花雕 发表于 2025-5-11 10:20:45

【花雕学编程】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 时间戳。





驴友花雕 发表于 2025-5-11 10:26:00

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口返回情况


驴友花雕 发表于 2025-5-11 11:02:43

【花雕学编程】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);// 确保绘图器稳定显示波形
}


驴友花雕 发表于 2025-5-11 11:07:19

【花雕学编程】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 模块精准控制矩形波,并在串口绘图器显示。




驴友花雕 发表于 2025-5-11 11:12:43

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口返回情况


驴友花雕 发表于 2025-5-11 11:25:45

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口绘图器返回情况




驴友花雕 发表于 2025-5-11 11:28:06

【花雕学编程】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 秒更新一次数据**
}

驴友花雕 发表于 2025-5-11 11:32:18

【花雕学编程】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 模块管理报警,并在串口监视器查看报警状态。




驴友花雕 发表于 2025-5-11 11:34:35

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口返回情况


驴友花雕 发表于 2025-5-11 13:42:44

【花雕学编程】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() 不执行任何操作
}


驴友花雕 发表于 2025-5-11 13:47:58

【花雕学编程】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 模块精准管理时间,并格式化输出到串口。





驴友花雕 发表于 2025-5-11 13:50:57

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口返回情况


驴友花雕 发表于 2025-5-11 14:26:27

【花雕学编程】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;
}

驴友花雕 发表于 2025-5-11 14:32:00

【花雕学编程】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 的时钟。





驴友花雕 发表于 2025-5-11 14:36:18

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口返回情况


驴友花雕 发表于 2025-5-11 17:13:14

【花雕学编程】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);
}   

驴友花雕 发表于 2025-5-11 17:16:59

【花雕学编程】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 模块不断读取时间、日期、温度和闹钟状态,并在串口监视器显示。




驴友花雕 发表于 2025-5-11 17:19:00

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

实验串口返回情况


驴友花雕 发表于 2025-5-11 18:22:41

【花雕学编程】Arduino动手做(245)--DS3231高精度时钟模块

【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十五:DS3231 高精度时钟模块IIC/I2C接口 实时计时传感器
项目之十:将时间居中显示在 OLED 屏幕上

安装RTClib.h库 (https://github.com/adafruit/RTClib)



驴友花雕 发表于 2025-5-11 18:25:00

【花雕学编程】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 屏幕**
}

页: 1 [2] 3
查看完整版本: 【花雕学编程】Arduino动手做(245)--DS3231模块12个小实验