授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。
1.玩转u8g2 OLED库,一篇就够
2.玩转u8g2 OLED库,一篇就够(字数太多 要分篇)
3.玩转u8g2 OLED库 + MAX7219_32X8点阵模块 (绝对被拒绝的表白神器)
4.玩转 RTC时钟库 + DS1302
5.玩转 RTC时钟库 + DS3231
6.玩转ArduinoJson库 V5版本
7.玩转ArduinoJson库 V6版本
8.玩转PubSubClient MQTT库
最近博主在弄8266编程的时候,偶然发现两个全新时钟模块压仓货:
为了避免资源浪费以及重复编写代码,博主还是抱着尝试的心态去寻找能够同时兼容 DS1302、DS3231甚至其他的时钟模块的第三方库。终于,还是被我找到了 —— Rtc 时钟库。
代码非常直接明了,分别支持了DS1302、DS1307、DS3231、DS3234。但是由于博主资源限制,本篇只会讨论DS1302以及DS3231,其他请读者自行学习。
网上介绍DS1302的帖子非常多,博主在这里就不从零开始讲解,这里推荐一个博主觉得写得还可以的参考文档 STM32与DS1302设计时钟芯片,超详细。
认真看完上面参考文档之后,博主得到几个我比较关心的点:
接下来看看常用电路图以及引脚定义:
操作DS1302的大致过程,就是将各种数据或者控制命令写入DS1302的寄存器来完成对应操作(比如设置时间、写保护操作)。然后使DS1302开始运作,DS1302时钟会按照设置情况运转,再用单片机将其寄存器内的数据读出。再用液晶显示,就是我们常说的简易电子钟。
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表。
此外,DS1302 还有控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
上面只是介绍理论,在理解理论的基础上,我们开始讲解RTC库的使用。以下是RTCDS1302库的源码(参考源码注释):
#ifndef __RTCDS1302_H__
#define __RTCDS1302_H__
#include
#include "RtcDateTime.h"
#include "RtcUtility.h"
//DS1302 Register Addresses 寄存器地址
const uint8_t DS1302_REG_TIMEDATE = 0x80;//秒寄存器
const uint8_t DS1302_REG_TIMEDATE_BURST = 0xBE;//时钟批量处理寄存器
const uint8_t DS1302_REG_TCR = 0x90;//涓流充电控制寄存器
const uint8_t DS1302_REG_RAM_BURST = 0xFE;//RAM批量处理寄存器
const uint8_t DS1302_REG_RAMSTART = 0xc0;//ram空间第一个字节
const uint8_t DS1302_REG_RAMEND = 0xfd;//ram空间最后一个字节
// ram read and write addresses are interleaved
const uint8_t DS1302RamSize = 31;//ram空间大小
// DS1302 Trickle Charge Control Register Bits 以下跟涓流充电有关 可忽略
enum DS1302TcrResistor {
DS1302TcrResistor_Disabled = 0,
DS1302TcrResistor_2KOhm = B00000001,
DS1302TcrResistor_4KOhm = B00000010,
DS1302TcrResistor_8KOhm = B00000011,
DS1302TcrResistor_MASK = B00000011,
};
enum DS1302TcrDiodes {
DS1302TcrDiodes_None = 0,
DS1302TcrDiodes_One = B00000100,
DS1302TcrDiodes_Two = B00001000,
DS1302TcrDiodes_Disabled = B00001100,
DS1302TcrDiodes_MASK = B00001100,
};
enum DS1302TcrStatus {
DS1302TcrStatus_Enabled = B10100000,
DS1302TcrStatus_Disabled = B01010000,
DS1302TcrStatus_MASK = B11110000,
};
const uint8_t DS1302Tcr_Disabled = DS1302TcrStatus_Disabled | DS1302TcrDiodes_Disabled | DS1302TcrResistor_Disabled;
// DS1302 Clock Halt Register & Bits
const uint8_t DS1302_REG_CH = 0x80; // bit in the seconds register 秒寄存器
const uint8_t DS1302_CH = 7;
// Write Protect Register & Bits
const uint8_t DS1302_REG_WP = 0x8E; //写保护寄存器
const uint8_t DS1302_WP = 7;
template<class T_WIRE_METHOD> class RtcDS1302
{
public:
RtcDS1302(T_WIRE_METHOD& wire) :
_wire(wire)
{
}
void Begin()
{
//会把三个引脚设置为输入状态
_wire.begin();
}
/**
* 判断是否写保护
* @return bool true表示写保护
*/
bool GetIsWriteProtected()
{
//获取写保护寄存器的值
uint8_t wp = getReg(DS1302_REG_WP);
//获取最高位的值
return !!(wp & _BV(DS1302_WP));
}
/**
* 设置是否写保护
* @param isWriteProtected
* true 写保护
* false 去掉写保护
*/
void SetIsWriteProtected(bool isWriteProtected)
{
//获取写保护寄存器的值
uint8_t wp = getReg(DS1302_REG_WP);
if (isWriteProtected)
{
wp |= _BV(DS1302_WP);
}
else
{
wp &= ~_BV(DS1302_WP);
}
setReg(DS1302_REG_WP, wp);
}
bool IsDateTimeValid()
{
return GetDateTime().IsValid();
}
/**
* 判断时钟是否正在运行
* @return bool
* true 时钟运行
* false 时钟停振,进入低功耗态
*/
bool GetIsRunning()
{
uint8_t ch = getReg(DS1302_REG_CH);
return !(ch & _BV(DS1302_CH));
}
void SetIsRunning(bool isRunning)
{
uint8_t ch = getReg(DS1302_REG_CH);
if (isRunning)
{
ch &= ~_BV(DS1302_CH);
}
else
{
ch |= _BV(DS1302_CH);
}
setReg(DS1302_REG_CH, ch);
}
uint8_t GetTrickleChargeSettings()
{
uint8_t setting = getReg(DS1302_REG_TCR);
return setting;
}
void SetTrickleChargeSettings(uint8_t setting)
{
if ((setting & DS1302TcrResistor_MASK) == DS1302TcrResistor_Disabled) {
// invalid resistor setting, set to disabled
setting = DS1302Tcr_Disabled;
goto apply;
}
if ((setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_Disabled ||
(setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_None) {
// invalid diode setting, set to disabled
setting = DS1302Tcr_Disabled;
goto apply;
}
if ((setting & DS1302TcrStatus_MASK) != DS1302TcrStatus_Enabled) {
// invalid status setting, set to disabled
setting = DS1302Tcr_Disabled;
goto apply;
}
apply:
setReg(DS1302_REG_TCR, setting);
}
/**
* 设置日期时间
* @param RtcDateTime 日期时间对象
*/
void SetDateTime(const RtcDateTime& dt)
{
// set the date time 批量设置时间
_wire.beginTransmission(DS1302_REG_TIMEDATE_BURST);
_wire.write(Uint8ToBcd(dt.Second()));//秒数
_wire.write(Uint8ToBcd(dt.Minute()));//分钟
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
_wire.write(Uint8ToBcd(dt.Day()));//天数
_wire.write(Uint8ToBcd(dt.Month()));//月份
// RTC Hardware Day of Week is 1-7, 1 = Monday
// convert our Day of Week to Rtc Day of Week
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
_wire.write(Uint8ToBcd(rtcDow));
_wire.write(Uint8ToBcd(dt.Year() - 2000));//年份
_wire.write(0); // no write protect, as all of this is ignored if it is protected
_wire.endTransmission();//批量写入寄存器
}
/**
* 获取日期时间
* @return RtcDateTime 日期时间对象
*/
RtcDateTime GetDateTime()
{
// set the date time 批量获取时间
_wire.beginTransmission(DS1302_REG_TIMEDATE_BURST | THREEWIRE_READFLAG);
uint8_t second = BcdToUint8(_wire.read() & 0x7F);//秒数
uint8_t minute = BcdToUint8(_wire.read());//分钟
uint8_t hour = BcdToBin24Hour(_wire.read());//小时
uint8_t dayOfMonth = BcdToUint8(_wire.read());//天数
uint8_t month = BcdToUint8(_wire.read());//月份
_wire.read(); // throwing away day of week as we calculate it
uint16_t year = BcdToUint8(_wire.read()) + 2000;//年份
_wire.read(); // throwing away write protect flag
_wire.endTransmission();//批量处理
//返回日期时间对象
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
}
/***
* 往RTC Memory写入数据
* @param memoryAddress 地址偏移量
* @param value 数据
*/
void SetMemory(uint8_t memoryAddress, uint8_t value)
{
// memory addresses interleaved read and write addresses
// so we need to calculate the offset
uint8_t address = memoryAddress * 2 + DS1302_REG_RAMSTART;
if (address <= DS1302_REG_RAMEND)
{
setReg(address, value);
}
}
uint8_t GetMemory(uint8_t memoryAddress)
{
uint8_t value = 0;
// memory addresses interleaved read and write addresses
// so we need to calculate the offset
uint8_t address = memoryAddress * 2 + DS1302_REG_RAMSTART;
if (address <= DS1302_REG_RAMEND)
{
value = getReg(address);
}
return value;
}
uint8_t SetMemory(const uint8_t* pValue, uint8_t countBytes)
{
uint8_t countWritten = 0;
//批量处理
_wire.beginTransmission(DS1302_REG_RAM_BURST);
while (countBytes > 0 && countWritten < DS1302RamSize)
{
_wire.write(*pValue++);
countBytes--;
countWritten++;
}
_wire.endTransmission();
//返回写入数量
return countWritten;
}
uint8_t GetMemory(uint8_t* pValue, uint8_t countBytes)
{
uint8_t countRead = 0;
_wire.beginTransmission(DS1302_REG_RAM_BURST | THREEWIRE_READFLAG);
while (countBytes > 0 && countRead < DS1302RamSize)
{
*pValue++ = _wire.read();
countRead++;
countBytes--;
}
_wire.endTransmission();
return countRead;
}
private:
T_WIRE_METHOD& _wire;
uint8_t getReg(uint8_t regAddress)
{
_wire.beginTransmission(regAddress | THREEWIRE_READFLAG);
uint8_t regValue = _wire.read();
_wire.endTransmission();
return regValue;
}
void setReg(uint8_t regAddress, uint8_t regValue)
{
_wire.beginTransmission(regAddress);
_wire.write(regValue);
_wire.endTransmission();
}
};
#endif // __RTCDS1302_H__
函数说明:
/**
* 初始化,会把三个引脚设置为输入状态
*/
void Begin();
函数说明:
/**
* 判断是否写保护
* @return bool true表示写保护
*/
bool GetIsWriteProtected();
源码说明:
bool GetIsWriteProtected()
{
//获取写保护寄存器的值
uint8_t wp = getReg(DS1302_REG_WP);
//获取最高位的值
return !!(wp & _BV(DS1302_WP));
}
函数说明:
/**
* 设置是否写保护
* @param isWriteProtected
* true 写保护
* false 去掉写保护
*/
void SetIsWriteProtected(bool isWriteProtected)
源码说明:
void SetIsWriteProtected(bool isWriteProtected)
{
//获取写保护寄存器的值
uint8_t wp = getReg(DS1302_REG_WP);
if (isWriteProtected)
{
wp |= _BV(DS1302_WP);
}else{
wp &= ~_BV(DS1302_WP);
}
setReg(DS1302_REG_WP, wp);
}
函数说明:
/**
* 判断时钟是否正在运行
* @return bool
* true 时钟运行
* false 时钟停振,进入低功耗态
*/
bool GetIsRunning()
源码说明:
bool GetIsRunning()
{
//判断秒寄存器的最高位数值
uint8_t ch = getReg(DS1302_REG_CH);
return !(ch & _BV(DS1302_CH));
}
函数说明:
/**
* 设置时钟是否运行
* @param isRunning
* true 时钟运行
* false 时钟停振,进入低功耗态
*/
void SetIsRunning(bool isRunning)
源码说明:
void SetIsRunning(bool isRunning)
{
uint8_t ch = getReg(DS1302_REG_CH);
if (isRunning){
ch &= ~_BV(DS1302_CH);
}else{
ch |= _BV(DS1302_CH);
}
//设置秒寄存器的最高位
setReg(DS1302_REG_CH, ch);
}
函数说明:
/**
* 设置日期时间
* @param RtcDateTime 日期时间对象
*/
void SetDateTime(const RtcDateTime& dt)
源码说明:
/**
* 设置日期时间
* @param RtcDateTime 日期时间对象
*/
void SetDateTime(const RtcDateTime& dt)
{
// set the date time 批量设置时间
_wire.beginTransmission(DS1302_REG_TIMEDATE_BURST);
_wire.write(Uint8ToBcd(dt.Second()));//秒数
_wire.write(Uint8ToBcd(dt.Minute()));//分钟
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
_wire.write(Uint8ToBcd(dt.Day()));//天数
_wire.write(Uint8ToBcd(dt.Month()));//月份
// RTC Hardware Day of Week is 1-7, 1 = Monday
// convert our Day of Week to Rtc Day of Week
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
_wire.write(Uint8ToBcd(rtcDow));
_wire.write(Uint8ToBcd(dt.Year() - 2000));//年份
_wire.write(0); // no write protect, as all of this is ignored if it is protected
_wire.endTransmission();//批量写入寄存器
}
参数说明:
class RtcDateTime
{
public:
RtcDateTime(uint32_t secondsFrom2000 = 0);
RtcDateTime(uint16_t year,
uint8_t month,
uint8_t dayOfMonth,
uint8_t hour,
uint8_t minute,
uint8_t second) :
_yearFrom2000((year >= c_OriginYear) ? year - c_OriginYear : year),
_month(month),
_dayOfMonth(dayOfMonth),
_hour(hour),
_minute(minute),
_second(second)
{
}
// RtcDateTime compileDateTime(__DATE__, __TIME__);
RtcDateTime(const char* date, const char* time);
bool IsValid() const;
uint16_t Year() const
{
return c_OriginYear + _yearFrom2000;
}
uint8_t Month() const
{
return _month;
}
uint8_t Day() const
{
return _dayOfMonth;
}
uint8_t Hour() const
{
return _hour;
}
uint8_t Minute() const
{
return _minute;
}
uint8_t Second() const
{
return _second;
}
// 0 = Sunday, 1 = Monday, ... 6 = Saturday
uint8_t DayOfWeek() const;
// 32-bit times as seconds since 1/1/2000
uint32_t TotalSeconds() const;
uint64_t TotalSeconds64() const;
// add seconds
void operator += (uint32_t seconds)
{
RtcDateTime after = RtcDateTime( TotalSeconds() + seconds );
*this = after;
}
// remove seconds
void operator -= (uint32_t seconds)
{
RtcDateTime before = RtcDateTime( TotalSeconds() - seconds );
*this = before;
}
// allows for comparisons to just work (==, <, >, <=, >=, !=)
operator uint32_t() const
{
return TotalSeconds();
}
// Epoch32 support
uint32_t Epoch32Time() const
{
return TotalSeconds() + c_Epoch32OfOriginYear;
}
void InitWithEpoch32Time(uint32_t time)
{
_initWithSecondsFrom2000<uint32_t>(time - c_Epoch32OfOriginYear);
}
// Epoch64 support
uint64_t Epoch64Time() const
{
return TotalSeconds64() + c_Epoch32OfOriginYear;
}
void InitWithEpoch64Time(uint64_t time)
{
_initWithSecondsFrom2000<uint64_t>(time - c_Epoch32OfOriginYear);
}
void InitWithIso8601(const char* date);
// convert our Day of Week to Rtc Day of Week
// RTC Hardware Day of Week is 1-7, 1 = Monday
static uint8_t ConvertDowToRtc(uint8_t dow)
{
if (dow == 0)
{
dow = 7;
}
return dow;
}
// convert Rtc Day of Week to our Day of Week
static uint8_t ConvertRtcToDow(uint8_t rtcDow)
{
return (rtcDow % 7);
}
protected:
uint8_t _yearFrom2000;
uint8_t _month;
uint8_t _dayOfMonth;
uint8_t _hour;
uint8_t _minute;
uint8_t _second;
template <typename T> void _initWithSecondsFrom2000(T secondsFrom2000)
{
_second = secondsFrom2000 % 60;
T timeFrom2000 = secondsFrom2000 / 60;
_minute = timeFrom2000 % 60;
timeFrom2000 /= 60;
_hour = timeFrom2000 % 24;
T days = timeFrom2000 / 24;
T leapDays;
for (_yearFrom2000 = 0;; ++_yearFrom2000)
{
leapDays = (_yearFrom2000 % 4 == 0) ? 1 : 0;
if (days < 365U + leapDays)
break;
days -= 365 + leapDays;
}
for (_month = 1;; ++_month)
{
uint8_t daysPerMonth = pgm_read_byte(c_daysInMonth + _month - 1);
if (leapDays && _month == 2)
daysPerMonth++;
if (days < daysPerMonth)
break;
days -= daysPerMonth;
}
_dayOfMonth = days + 1;
}
};
函数说明:
/**
* 获取日期时间
* @return RtcDateTime 日期时间对象
*/
RtcDateTime GetDateTime()
源码说明:
RtcDateTime GetDateTime()
{
// set the date time 批量获取时间
_wire.beginTransmission(DS1302_REG_TIMEDATE_BURST | THREEWIRE_READFLAG);
uint8_t second = BcdToUint8(_wire.read() & 0x7F);//秒数
uint8_t minute = BcdToUint8(_wire.read());//分钟
uint8_t hour = BcdToBin24Hour(_wire.read());//小时
uint8_t dayOfMonth = BcdToUint8(_wire.read());//天数
uint8_t month = BcdToUint8(_wire.read());//月份
_wire.read(); // throwing away day of week as we calculate it
uint16_t year = BcdToUint8(_wire.read()) + 2000;//年份
_wire.read(); // throwing away write protect flag
_wire.endTransmission();//批量处理
//返回日期时间对象
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
}
函数说明:
/***
* 往RTC Memory写入数据
* @param memoryAddress 地址偏移量
* @param value 数据
*/
void SetMemory(uint8_t memoryAddress, uint8_t value)
/**
* 往RTC Memory批量写入数据
* @param pValue 批量数据
* @param countBytes 数据字节数
*/
uint8_t SetMemory(const uint8_t* pValue, uint8_t countBytes)
源码说明:
void SetMemory(uint8_t memoryAddress, uint8_t value)
{
// memory addresses interleaved read and write addresses
// so we need to calculate the offset
uint8_t address = memoryAddress * 2 + DS1302_REG_RAMSTART;
if (address <= DS1302_REG_RAMEND)
{
setReg(address, value);
}
}
uint8_t SetMemory(const uint8_t* pValue, uint8_t countBytes)
{
uint8_t countWritten = 0;
//批量处理
_wire.beginTransmission(DS1302_REG_RAM_BURST);
while (countBytes > 0 && countWritten < DS1302RamSize)
{
_wire.write(*pValue++);
countBytes--;
countWritten++;
}
_wire.endTransmission();
//返回写入数量
return countWritten;
}
函数说明:
/***
* 读取RTC Memory
* @param memoryAddress 地址偏移量
* @return 数据
*/
uint8_t GetMemory(uint8_t memoryAddress)
/***
* 批量读取RTC Memory
* @param pValue 存储空间
* @param countBytes 数据字节数
*/
uint8_t GetMemory(uint8_t* pValue, uint8_t countBytes)
源码说明:
uint8_t GetMemory(uint8_t memoryAddress)
{
uint8_t value = 0;
// memory addresses interleaved read and write addresses
// so we need to calculate the offset
uint8_t address = memoryAddress * 2 + DS1302_REG_RAMSTART;
if (address <= DS1302_REG_RAMEND)
{
value = getReg(address);
}
return value;
}
uint8_t GetMemory(uint8_t* pValue, uint8_t countBytes)
{
uint8_t countRead = 0;
_wire.beginTransmission(DS1302_REG_RAM_BURST | THREEWIRE_READFLAG);
while (countBytes > 0 && countRead < DS1302RamSize)
{
*pValue++ = _wire.read();
countRead++;
countBytes--;
}
_wire.endTransmission();
return countRead;
}
DS1302采用三总线方式,SCLK(CLK), IO (DAT), CE (RST)。
实验内容
实验器材
引脚连接
模块引脚 | Mega2560引脚 |
---|---|
VCC | VCC |
GND | GND |
DAT | 6 |
CLK | 5 |
RST | 7 |
实验代码
// CONNECTIONS:
// DS1302 CLK/SCLK --> 5
// DS1302 DAT/IO --> 6
// DS1302 RST/CE --> 7
// DS1302 VCC --> 3.3v - 5v
// DS1302 GND --> GND
#include
#include
ThreeWire myWire(/*IO*/6,/*SCLK*/5,/*CE*/7); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
void setup ()
{
Serial.begin(57600);
Serial.print("compiled: ");
Serial.print(__DATE__);
Serial.println(__TIME__);
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
printDateTime(compiled);
Serial.println();
if (Rtc.GetIsWriteProtected())
{
Serial.println("RTC was write protected, enabling writing now");
Rtc.SetIsWriteProtected(false);
}
if (!Rtc.GetIsRunning())
{
Serial.println("RTC was not actively running, starting now");
Rtc.SetIsRunning(true);
}
RtcDateTime now = Rtc.GetDateTime();
if (now < compiled)
{
Serial.println("RTC is older than compile time! (Updating DateTime)");
Rtc.SetDateTime(compiled);
}
else if (now > compiled)
{
Serial.println("RTC is newer than compile time. (this is expected)");
}
else if (now == compiled)
{
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
}
}
void loop ()
{
RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
Serial.println();
delay(10000); // ten seconds
}
#define countof(a) (sizeof(a) / sizeof(a[0]))
void printDateTime(const RtcDateTime& dt)
{
char datestring[20];
snprintf_P(datestring,
countof(datestring),
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
dt.Month(),
dt.Day(),
dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
Serial.print(datestring);
}
实验内容
实验器材
引脚连接
模块引脚 | Mega2560引脚 |
---|---|
VCC | VCC |
GND | GND |
DAT | 6 |
CLK | 5 |
RST | 7 |
实验代码
// CONNECTIONS:
// DS1302 CLK/SCLK --> 5
// DS1302 DAT/IO --> 6
// DS1302 RST/CE --> 7
// DS1302 VCC --> 3.3v - 5v
// DS1302 GND --> GND
#include
#include
ThreeWire myWire(/*IO*/6,/*SCLK*/5,/*CE*/7); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
#define countof(a) (sizeof(a) / sizeof(a[0]))
const char data[] = "danpianjicainiao";
void setup ()
{
Serial.begin(57600);
Serial.print("compiled: ");
Serial.print(__DATE__);
Serial.println(__TIME__);
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
printDateTime(compiled);
Serial.println();
if (Rtc.GetIsWriteProtected())
{
Serial.println("RTC was write protected, enabling writing now");
Rtc.SetIsWriteProtected(false);
}
if (!Rtc.GetIsRunning())
{
Serial.println("RTC was not actively running, starting now");
Rtc.SetIsRunning(true);
}
RtcDateTime now = Rtc.GetDateTime();
if (now < compiled)
{
Serial.println("RTC is older than compile time! (Updating DateTime)");
Rtc.SetDateTime(compiled);
}
/* comment out on a second run to see that the info is stored long term */
// Store something in memory on the RTC
uint8_t count = sizeof(data);
uint8_t written = Rtc.SetMemory((const uint8_t*)data, count); // this includes a null terminator for the string
if (written != count)
{
Serial.print("something didn't match, count = ");
Serial.print(count, DEC);
Serial.print(", written = ");
Serial.print(written, DEC);
Serial.println();
}
/* end of comment out section */
}
void loop ()
{
RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
Serial.println(" +");
delay(5000);
// read data
uint8_t buff[20];
const uint8_t count = sizeof(buff);
// get our data
uint8_t gotten = Rtc.GetMemory(buff, count);
if (gotten != count)
{
Serial.print("something didn't match, count = ");
Serial.print(count, DEC);
Serial.print(", gotten = ");
Serial.print(gotten, DEC);
Serial.println();
}
Serial.print("data read (");
Serial.print(gotten);
Serial.print(") = \"");
// print the string, but terminate if we get a null
for (uint8_t ch = 0; ch < gotten && buff[ch]; ch++)
{
Serial.print((char)buff[ch]);
}
Serial.println("\"");
delay(5000);
}
void printDateTime(const RtcDateTime& dt)
{
char datestring[20];
snprintf_P(datestring,
countof(datestring),
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
dt.Month(),
dt.Day(),
dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
Serial.print(datestring);
}
本博文讲解如何使用RTC时钟库来操作DS1302,同时附带源码解析,请关注下一篇DS3231.