回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【花雕学编程】Arduino动手做(245)---DS3231高精度时钟模块之通过 I2C 通信 接收用户输入的时间数据并更新时钟 简单

头像 驴友花雕 2025.05.11 8 0

00.jpg
02.jpg
04-.jpg
04--.jpg
06.jpg

  【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[20];  // 存储输入的时间字符串

    uint8_t currentPos = 0;
    while (!isStrComplete) {
        if (Serial.available()) {
            inputChar = Serial.read();
            inputStr[currentPos] = 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[i] == 'x') {
            posX = i;
            break;
        }
    }

    // **ASCII 码 '0' 的值(用于转换字符为数字)**
    uint8_t zeroAscii = '0';

    // **解析年**
    temp1 = (byte)inputStr[posX - 13] - zeroAscii;
    temp2 = (byte)inputStr[posX - 12] - zeroAscii;
    year = temp1 * 10 + temp2;

    // **解析月**
    temp1 = (byte)inputStr[posX - 11] - zeroAscii;
    temp2 = (byte)inputStr[posX - 10] - zeroAscii;
    month = temp1 * 10 + temp2;

    // **解析日期**
    temp1 = (byte)inputStr[posX - 9] - zeroAscii;
    temp2 = (byte)inputStr[posX - 8] - zeroAscii;
    date = temp1 * 10 + temp2;

    // **解析星期**
    dow = (byte)inputStr[posX - 7] - zeroAscii;

    // **解析小时**
    temp1 = (byte)inputStr[posX - 6] - zeroAscii;
    temp2 = (byte)inputStr[posX - 5] - zeroAscii;
    hour = temp1 * 10 + temp2;

    // **解析分钟**
    temp1 = (byte)inputStr[posX - 4] - zeroAscii;
    temp2 = (byte)inputStr[posX - 3] - zeroAscii;
    minute = temp1 * 10 + temp2;

    // **解析秒**
    temp1 = (byte)inputStr[posX - 2] - zeroAscii;
    temp2 = (byte)inputStr[posX - 1] - zeroAscii;
    second = temp1 * 10 + temp2;
}

代码简单解读

这段代码使用 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 的时钟。


实验串口返回情况

 

11.jpg

08-1.jpg

评论

user-avatar
icon 他的勋章
    展开更多