深入解析 Adafruit DS3231 精密 RTC 模块:从特性到应用

电子说

1.4w人已加入

描述

深入解析 Adafruit DS3231 精密 RTC 模块:从特性到应用

在电子设计领域,精确的时间记录至关重要。无论是数据记录器、时钟设备,还是需要精确时间戳的应用场景,一个可靠的实时时钟(RTC)都是不可或缺的。今天,我们就来深入探讨一下 Adafruit 公司推出的 DS3231 精密 RTC 模块,看看它有哪些独特之处,以及如何在实际项目中使用它。

文件下载:3013.pdf

一、DS3231 简介

DS3231 是一款 “Extremely Accurate I²C Integrated RTC/TCXO/Crystal”(极其精确的 I²C 集成实时时钟/温补晶体振荡器/晶体)芯片。它的最大亮点在于将晶体集成在芯片内部,同时配备了温度传感器。一般的 RTC 大多使用外部 32kHz 定时晶体,虽然这种晶体能以低电流消耗来保持时间,但在温度变化时会有轻微的漂移。而 DS3231 的温度传感器可以通过增加或减少时钟脉冲来补偿频率变化,从而保证时间的精确记录。

Adafruit 为这款芯片打造了一款小巧的、适合面包板使用的开发板,并且配备了支持即插即用的 STEMMA QT 连接器,大大降低了使用难度。此外,该模块支持 2.3V 至 5.5V 的电源输入,可以兼容 3.3V(如 Feather/Raspberry Pi)或 5V(如 Arduino/Metro328)的逻辑电平。只要在背面插入一枚硬币电池,即使主电源丢失,也能实现数年的精确时间记录。

二、引脚定义

电源引脚

  • Vin:电源输入引脚。由于 RTC 可以在 2.3V 至 5.5V 的电源下工作,因此对于 3.3V 或 5V 的逻辑/电源,无需额外的稳压器或电平转换器。为开发板供电时,应提供与微控制器逻辑电平相同的电源,例如对于 5V 的 Arduino 微控制器,应使用 5V 电源。
  • GND:电源和逻辑的公共接地端。

I2C 逻辑引脚

  • SCL:I2C 时钟引脚,连接到微控制器的 I2C 时钟线。该引脚具有一个 10K 上拉电阻连接到 Vin。
  • SDA:I2C 数据引脚,连接到微控制器的 I2C 数据线。同样,该引脚也具有一个 10K 上拉电阻连接到 Vin。
  • STEMMA QT:仅适用于 STEMMA QT 版本的开发板。这些连接器允许您连接到具有 STEMMA QT 连接器的开发板,或者通过各种相关配件连接到其他设备。

其他引脚

  • BAT:与电池的正极焊盘相连。如果需要从硬币电池为其他设备供电,或者使用不同的独立电池提供备用电源,可以使用该引脚。VBat 电压范围为 2.3V 至 5.5V,当主电源 Vin 丢失时,DS3231 会自动切换到备用电源。
  • 32K:32KHz 振荡器输出。为开漏输出,若要从微控制器引脚读取该信号,需要外接上拉电阻。
  • SQW:可选的方波或中断输出。同样是开漏输出,读取信号时需要外接上拉电阻。
  • RST:与大多数复位引脚不同,它不仅是一个输入引脚,还可用于复位外部设备或指示主电源丢失。为开漏输出,但内部有一个 50K 上拉电阻。只要 Vin 存在,上拉电阻会使该引脚电压保持为高电平;当 Vin 下降且芯片切换到电池备用状态时,该引脚变为低电平。

三、组装步骤

准备排针

如果需要,将排针裁剪至合适的长度。为了便于焊接,可以将排针插入面包板,长引脚朝下。

安装开发板

将开发板放置在排针上,使短引脚穿过开发板的焊盘。

焊接

确保焊接所有引脚,以实现可靠的电气连接。如果您对焊接操作不太熟悉,可以参考 Adafruit 的《优秀焊接指南》(https://adafru.it/aTk)。焊接完成后,目视检查焊点,并继续后续步骤。同时,不要忘记为实时时钟安装电池备用电源,将 CR1220 尺寸的电池安装在开发板背面,安装时确保电池上的 “+” 号可见。

四、Arduino 使用方法

硬件连接

将开发板轻松连接到任何具有 I2C 接口的微控制器,这里以 Arduino 为例:

  • 将 Vin(红色线)连接到 3 - 5V 的电源,使用与微控制器逻辑电平相同的电压。对于大多数 Arduino 来说,通常是 5V。
  • 将 GND(黑色线)连接到公共电源/数据接地端。
  • 将 SCL(黄色线)引脚连接到 Arduino 的 I2C 时钟 SCL 引脚。对于基于 UNO 和 '328 的 Arduino,该引脚也称为 A5;对于 Mega,为数字引脚 21;对于 Leonardo/Micro,为数字引脚 3。
  • 将 SDA(蓝色线)引脚连接到 Arduino 的 I2C 数据 SDA 引脚。对于基于 UNO 和 '328 的 Arduino,该引脚也称为 A4;对于 Mega,为数字引脚 20;对于 Leonardo/Micro,为数字引脚 2。需要注意的是,DS3231 的默认 I2C 地址为 0x68,且不可更改。

下载 RTCLib 库

我们将使用 JeeLab 的优秀 RTC 库 RTClib 的一个分支(https://adafru.it/aX2),这是一个用于从 RTC 获取和设置时间的库。从 Arduino 库管理器中搜索并安装 Adafruit 的 RTCLib 库。如果您对 Arduino 库的安装不太熟悉,可以参考 Adafruit 的教程:http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use(https://adafru.it/aYM)。

首次 RTC 测试

在 Arduino 未通电或未连接 USB 的情况下,从电池座中取出电池,等待 3 秒钟后再将电池放回,这将重置 RTC 芯片。

加载示例代码

打开文件 -> 示例 -> RTClib -> ds3231,将代码上传到连接了 RTC 的 Arduino 上。上传完成后,在串口监视器中以 9600 波特率查看输出。几秒钟后,您将看到 Arduino 检测到 DS3231 首次上电,并根据 Arduino 代码设置时间。之后,断开 Arduino 和 RTC 几秒钟(或几分钟、几小时、几周),然后再重新连接。下次运行时,您将不会再看到 “RTC lost power” 消息,而是会立即获取到正确的时间。

读取时间

通过调用 RTClib 库中的 now() 函数来获取时间,该函数返回一个 DateTime 对象,其中包含了年、月、日、时、分、秒等信息。与一些 RTC 库中分别调用 RTC.year()RTC.hour() 等函数来获取当前时间的方法不同,now() 函数可以一次性获取时间的 “快照”,避免了在时间切换瞬间可能出现的时间不准确问题。此外,还可以通过调用 unixtime() 函数从 DateTime 对象中获取自 1970 年 1 月 1 日午夜以来的秒数(不包括闰秒),这对于计算时间间隔非常方便。

五、CircuitPython 使用方法

硬件连接

将 DS3231 按照前面 Arduino 部分所述的方式连接到您的开发板,即 Vin 连接到开发板的 3.3V 或 5V 输出,GND 连接到开发板的接地端,SCL 连接到开发板的 I2C SCL / 时钟线,SDA 连接到开发板的 I2C SDA / 数据线。

安装 CircuitPython 库

首先,确保您的开发板运行的是最新版本的 Adafruit CircuitPython 固件(https://adafru.it/tBa)。然后,从 Adafruit 的 CircuitPython 库捆绑包(https://adafru.it/zdx)中找到并安装必要的库。对于非 Express 板,如 Trinket M0、Gemma M0 和 Feather/Metro M0 basic,需要手动从捆绑包中安装以下库:adafruit_ds3231.mpyadafruit_bus_deviceadafruit_register。在继续之前,请确保开发板的 lib 文件夹或根文件系统中已经复制了这些文件和文件夹。

代码示例与使用

连接到开发板的串行 REPL(https://adafru.it/pMf),在 CircuitPython 的 >>> 提示符下进行操作。首先,导入必要的 board 模块来初始化 I2C 总线:

import board
i2c = board.I2C()

对于一些没有硬件 I2C 接口的开发板,如 ESP8266,可能需要导入并使用 bitbangio 模块:

import board
import bitbangio
i2c = bitbangio.I2C(board.SCL, board.SDA)

接下来,导入 DS3231 模块并创建一个 DS3231 类的实例:

import adafruit_ds3231
ds3231 = adafruit_ds3231.DS3231(i2c)

此时,您就可以读取和设置时钟的时间了。通过访问 DS3231 实例的 datetime 属性来实现这一功能。例如,读取时间可以使用以下代码:

print(ds3231.datetime)

时间将以特殊的 Python 时间结构(https://adafru.it/C4x)返回,该结构具有 tm_yeartm_montm_mday 等属性。如果时间尚未设置,默认值为 2000 年 1 月 1 日。要设置时间,可以使用以下代码:

import time
ds3231.datetime = time.struct_time((2017, 1, 1, 0, 0, 0, 6, 1, -1))

最后,这里提供一个完整的示例程序,将其保存为 main.py 并上传到开发板,您将看到时间和日期每秒打印一次到 REPL:

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Change the if False to if True below to set the time, otherwise it will just
# Simple demo of reading and writing the time for the DS3231 real-time clock.
# print the current date and time every second. Notice also comments to adjust
# for working with hardware vs. software I2C.
import time
import board
import adafruit_ds3231

i2c = board.I2C()  # uses board.SCL and board.SDA
rtc = adafruit_ds3231.DS3231(i2c)

# Lookup table for names of days (nicer printing).
days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
"Saturday")

# pylint: disable-msg=using-constant-test
if False:  # change to True if you want to set the time!
    # year, mon, date, hour, min, sec, wday, yday, isdst
    t = time.struct_time((2017, 10, 29, 15, 14, 15, 0, -1, -1))
    # you must set year, mon, date, hour, min, sec and weekday
    # yearday is not supported, isdst can be set but we don't do anything with it 
    at this time
    print("Setting time to:", t)  # uncomment for debugging
    rtc.datetime = t
# pylint: enable-msg=using-constant-test
print()

# Main loop:
while True:
    t = rtc.datetime
    print(
        "The date is {} {}/{}/{}".format(
            days[int(t.tm_wday)], t.tm_mday, t.tm_mon, t.tm_year
        )
    )
    print("The time is {}:{:02}:{:02}".format(t.tm_hour, t.tm_min, t.tm_sec))
    time.sleep(1)  # wait a second

六、资料下载

在进行开发过程中,您可能需要以下相关资料:

综上所述,Adafruit DS3231 精密 RTC 模块以其高精度、低功耗和易于使用的特点,成为电子工程师在时间记录相关项目中的理想选择。无论是初学者还是有经验的工程师,都可以通过简单的连接和编程,轻松实现精确的时间记录功能。您在使用 DS3231 模块的过程中遇到过哪些问题呢?欢迎在评论区分享您的经验和心得。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分