最近更新于 2023-11-13 18:53

前言

file

这个模块通过 DS1302 芯片进行计时,支持年、月、日、周、时、分、秒,对于闰年以及不同月份不同天数可以自动调整,可以按 12 小时制或 24 小时制工作。芯片中有 31 Byte 的 SRAM,当前时钟就存储在里面。可以通过串行接口和单片机通信,模块上的电池可以保证在断开 VCC 引脚连接后依然正常工作,不依赖引脚供电。

测试环境

Arduino UNO
Arduino IDE 2.1.1(
Ds1302 1.0.4:https://github.com/Treboada/Ds1302

接线

\begin{array}{|c|c|}
\hline
DS1302 模块 & Arduino \\
\hline
VCC & 5V \\
\hline
GND & GND \\
\hline
CLK & 2 \\
\hline
DAT & 3 \\
\hline
RST & 4 \\
\hline
\end{array}

进行串行通信的接口连接的 3 个引脚可以自定,只是要和代码匹配

代码示例

设置时间

#include <Ds1302.h>

#define CLK     2
#define DAT     3
#define RST     4

Ds1302 rtc(RST, CLK, DAT);

uint8_t parseDigits(char* str, uint8_t count)
{
  uint8_t val = 0;
  while (count-- > 0) {
    val = (val * 10) + (*str++ - '0');
  }
  return val;
}

void setup()
{
  rtc.init();

  Serial.begin(9600);
  Serial.println("请输入日期和时间 (YYMMDDWhhmmss): ");
}

void loop()
{
  static char buffer[13];
  static uint8_t char_idx = 0;

  if (char_idx == 13)
  {
    Ds1302::DateTime dt;

    dt.year = parseDigits(buffer, 2);
    dt.month = parseDigits(buffer + 2, 2);
    dt.day = parseDigits(buffer + 4, 2);
    dt.dow = parseDigits(buffer + 6, 1);
    dt.hour = parseDigits(buffer + 7, 2);
    dt.minute = parseDigits(buffer + 9, 2);
    dt.second = parseDigits(buffer + 11, 2);

    rtc.setDateTime(&dt);

    char_idx = 0;
  }

  if (Serial.available())
  {
    buffer[char_idx++] = Serial.read();
  }
}

比如要设置时间为 2023-8-20 星期日 19:00:00,则输入 2308207190000
file

读取时间

#include <Ds1302.h>

#define CLK     2
#define DAT     3
#define RST     4

Ds1302 rtc(RST, CLK, DAT);

const static char* WeekDays[] =
{
    "星期一",
    "星期二",
    "星期三",
    "星期四",
    "星期五",
    "星期六",
    "星期日"
};

void setup()
{
    Serial.begin(9600);

    rtc.init(); // 初始化实时时钟模块

    // 首次使用没有设置时间,需要先设置时间再启动
    if (rtc.isHalted())
    {
        Serial.println("实时时钟模块已停止,正在设置时间......");

        Ds1302::DateTime dt =
        {
            .year = 23,
            .month = Ds1302::MONTH_AUG,
            .day = 20,
            .hour = 19,
            .minute = 00,
            .second = 00,
            .dow = Ds1302::DOW_SUN
        };

        rtc.setDateTime(&dt);
    }
}

void loop()
{
    Ds1302::DateTime now;
    rtc.getDateTime(&now); // 读取当前时间

    static uint8_t last_second = 0;
    if (last_second != now.second)
    {
        last_second = now.second;

        Serial.print("20");
        Serial.print(now.year);
        Serial.print('-');

        if (now.month < 10)
        {
            Serial.print('0');
        }
        Serial.print(now.month);
        Serial.print('-');

        if (now.day < 10)
        {
            Serial.print('0');
        }
        Serial.print(now.day);
        Serial.print(' ');

        Serial.print(WeekDays[now.dow - 1]);
        Serial.print(' ');

        if (now.hour < 10)
        {
            Serial.print('0');
        }
        Serial.print(now.hour);
        Serial.print(':');

        if (now.minute < 10)
        {
            Serial.print('0');
        }
        Serial.print(now.minute);
        Serial.print(':');

        if (now.second < 10)
        {
            Serial.print('0');
        }
        Serial.print(now.second);
        Serial.println();
    }

    delay(200);
}

file