风筝
发表于: 2022-7-26 16:53:58 | 显示全部楼层

我们都知道,用于项目的大多数MCU都与时间无关。简单地说,他们不知道周围的时间。对于大多数项目来说都可以,但偶尔当您想到保持时间是首要考虑因素时,DS1307实时时钟模块就是一个不错的选择。它非常适合包含数据记录、时钟构建、时间戳、计时器和警报的项目。


DS1307实时时钟芯片

该模块主要采用Maxim公司的低成本、极其精确的实时时钟芯片 – DS1307。它管理所有计时功能,并具有一个简单的两线I2C接口,可轻松与您选择的任何微控制器连接。

DS1307-Module-Chip-Crystal-Oscillator.jpg


该芯片维护秒、分、小时、星期、日期、月份和年份信息。对于少于31天的月份,月末的日期会自动调整,包括闰年的更正(直到2100年有效)。时钟以24小时制或12小时制运行,带有AM/PM指示器。它还提供两个可编程的时间警报。


该模块的另一个很酷的功能是SQW引脚,它可以输出1Hz、4kHz、8kHz或32kHz的漂亮方波,并且可以通过编程方式进行处理。


DS1307带有一个用于计时的外部32kHz晶振。但是这些晶体的问题是外部温度会影响它们的振荡频率。这种频率变化可以忽略不计,但肯定会增加。这听起来像是一个问题,但事实并非如此。 实际上,它的结果是时钟每月大约减少五分钟左右。


后备电池

DS1307包含电池输入,并在设备的主电源中断时保持准确的计时。


内置电源检测电路持续监控VCC状态以检测电源故障并自动切换到备用电源。因此,您不必担心停电,您的MCU仍然可以跟踪时间。

DS1307-Module-CR2032-Battery-Holder.jpg


电路板的背面装有一个用于20毫米3V纽扣锂电池的电池座。任何CR2032电池都可以很好地安装。


假设使用容量为47mAh的充满电的CR2032电池并且芯片消耗其最小300nA电流,则该电池可以在没有外部5V电源的情况下使RTC运行至少17.87年。

47mAh/300nA = 156666.67 小时 = 6527.78 天 = 17.87 年


板载24C32 EEPROM

DS1307 RTC模块还配备了一颗Atmel公司的32 字节24C32 EEPROM芯片,具有一定的读写周期。它可以用来保存设置或任何东西。

DS1307-Module-24C32-EEPROM-Chip.jpg


24C32 EEPROM使用I2C接口进行通信,并与DS1307共享相同的I2C总线。板载的24C32 EEPROM具有硬接线的I2C地址并设置为0x50。


模块的隐藏功能 – DS18B20

DS1307实时时钟模块上有一项经常被忽视的功能,它允许我们安装一个DS18B20温度传感器。


电池座旁边右上角的3个通孔(标记为U1)是安装DS18B20的位置。

DS1307-Module-Provision-for-DS18B20.jpg


安装DS18B20后,您将能够从DS引脚获取温度读数。 这些读数还可用于补偿代码中基于温度的时间漂移。按照丝印焊接DS18B20。 VCC和DS之间可能还需要一个4.7K电阻。


DS1307实时时钟模块引脚

DS1307实时时钟模块共有7个引脚与外界连接。连接如下:

DS1307-RTC-Module-Pinout.jpg


SQW 引脚输出四种方波频率1Hz、4kHz、8kHz或32kHz中的一种,并且可以通过编程方式启用。

DS 引脚应该输出温度读数,如果您的模块在电池座(标记为 U1)旁边安装了DS18B20温度传感器 。

SCL 是 I2C 接口的时钟输入,用于同步串行接口上的数据移动。

SDA 是 I2C 串行接口的数据输入/输出。

VCC 引脚为模块供电。它可以在3.3V至5.5V之间的任何电压。

GND 是接地引脚。

BAT 是任何3V锂电池或其他电源的备用电源输入,以在设备的主电源中断时保持准确的计时。


将DS1307实时时钟模块连接到Arduino UNO开发板

让我们将模块连接到Arduino。连接相当简单。首先将VCC引脚连接到Arduino上的5V输出,然后将GND接地。


现在我们剩下用于I2C通信的引脚。请注意,每个Arduino开发板都有不同的I2C引脚,应相应地连接。在Arduino R3开发板上,SDA(数据线)和 SCL(时钟线)位于靠近AREF引脚的引脚排针上。它们也被称为 A5 (SCL) 和 A4 (SDA)。


下图向您展示了如何连接所有组件。

Wiring-DS1307-RTC-module-with-Arduino.jpg


安装RTClib库

与RTC模块通信是一项繁重的工作。幸运的是,RTClib库可以帮我们隐藏所有复杂性,以便我们可以发出简单的命令来读取RTC数据。


要安装库,请导航到 Sketch > Include Library > Manage Libraries...等待库管理器下载库索引并更新已安装库的列表。

Manage-Libraries.jpg


通过输入“rtclib”过滤您的搜索。应该有几个条目。查找Adafruit公司的RTClib。单击该条目,然后选择安装。

Installing-RTClib-Arduino-library.jpg


Arduino代码 – 读取日期和时间

以下草图将让您全面了解如何在DS1307实时时钟模块上设置/读取日期和时间,并可以作为更多实际实验和项目的基础。

  1. #include <Wire.h>
  2. #include "RTClib.h"

  3. RTC_DS1307 rtc;

  4. char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

  5. void setup ()
  6. {
  7.   Serial.begin(9600);
  8.   delay(3000); // wait for console opening

  9.   if (! rtc.begin()) {
  10.     Serial.println("Couldn't find RTC");
  11.     while (1);
  12.   }

  13.   if (rtc.lostPower()) {
  14.     Serial.println("RTC lost power, lets set the time!");

  15.         // Comment out below lines once you set the date & time.
  16.     // Following line sets the RTC to the date & time this sketch was compiled
  17.     rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  18.     // Following line sets the RTC with an explicit date & time
  19.     // for example to set January 27 2017 at 12:56 you would call:
  20.     // rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
  21.   }
  22. }

  23. void loop ()
  24. {
  25.     DateTime now = rtc.now();

  26.     Serial.println("Current Date & Time: ");
  27.     Serial.print(now.year(), DEC);
  28.     Serial.print('/');
  29.     Serial.print(now.month(), DEC);
  30.     Serial.print('/');
  31.     Serial.print(now.day(), DEC);
  32.     Serial.print(" (");
  33.     Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  34.     Serial.print(") ");
  35.     Serial.print(now.hour(), DEC);
  36.     Serial.print(':');
  37.     Serial.print(now.minute(), DEC);
  38.     Serial.print(':');
  39.     Serial.print(now.second(), DEC);
  40.     Serial.println();

  41.     Serial.println("Unix Time: ");
  42.     Serial.print("elapsed ");
  43.     Serial.print(now.unixtime());
  44.     Serial.print(" seconds/");
  45.     Serial.print(now.unixtime() / 86400L);
  46.     Serial.println(" days since 1/1/1970");

  47.     // calculate a date which is 7 days & 30 seconds into the future
  48.     DateTime future (now + TimeSpan(7,0,0,30));

  49.     Serial.println("Future Date & Time (Now + 7days & 30s): ");
  50.     Serial.print(future.year(), DEC);
  51.     Serial.print('/');
  52.     Serial.print(future.month(), DEC);
  53.     Serial.print('/');
  54.     Serial.print(future.day(), DEC);
  55.     Serial.print(' ');
  56.     Serial.print(future.hour(), DEC);
  57.     Serial.print(':');
  58.     Serial.print(future.minute(), DEC);
  59.     Serial.print(':');
  60.     Serial.print(future.second(), DEC);
  61.     Serial.println();

  62.     Serial.println();
  63.     delay(1000);
  64. }
复制代码

这是串口监视器中输出的样子。

DS1307-Output-On-Serial-Monitor.jpg


代码说明

草图首先包含用于与模块通信的wire.h和RTClib.h库。然后我们创建一个RTClib库对象并定义daysOfTheWeek二维字符数组来存储天数信息。


在setup和loop函数中,我们使用以下函数与 RTC模块进行交互。


begin() 函数确保RTC模块已连接。

lostPower() 函数读取DS3231的内部I2C寄存器以检查芯片是否丢失了时间。如果函数返回true,我们就可以设置日期和时间。

adjust() 函数设置日期和时间。这是一个重载函数。

●    第一个重载函数 DateTime(F(__DATE__), F(__TIME__)) 设置草图编译的日期和时间。

●    第二个重载方法 DateTime(YYYY, M, D, H, M, s) 使用明确的日期和时间设置RTC。例如,设置为2017年1月27日12:56: rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));

now() 函数返回当前日期和时间。它的返回值通常存储在数据类型DateTime的变量中。

year() 函数返回当前年份。

month() 函数返回当前月份。

day() 函数返回当前日期。

dayOfTheWeek() 函数返回当前星期几。此函数通常用作二维字符数组的索引,该数组存储天数信息,如上述程序 daysOfTheWeek 中定义的

hour() 函数返回当前小时。

minute() 函数返回当前分钟。

second() 函数返回当前秒数。

unixtime() 函数以秒为单位返回unix时间。 Unix时间是用于描述时间点的系统。它是自00:00:00(称为协调世界时 - 1970年1月1日星期四)以来经过的秒数。

TimeSpan() 函数用于从当前时间添加/减去时间。您可以添加/减去天、小时、分钟和秒。它也是一个重载函数。

●    now() + TimeSpan(seconds) 返回当前时间加上秒数的未来时间。

●    now() - TimeSpan(days,hours, minutes, seconds) 返回过去的时间。



跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1480



手机版|

GMT+8, 2024-4-24 20:51 , Processed in 0.053841 second(s), 9 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表