Tiny RTC DS1307 时钟模块 完整代码(Arduino)及一些要注意的地方

       这个东西其实是可以的,就是没什么技术支持,有很多细节会有坑,我搞了十几天(期间还花了一周来学习焊接)才完全成功的,期间我很恼火,觉得就是买了个垃圾,甚至想扔掉这个2块钱的东西。于是我又买了一个,结果两个都是一样的,这时我才静下心来看看到底是怎么一回事。现在把经验细节分享给后来的新手,高手可以略过。

就今天写这篇博文的时候做的,童叟无欺哈

我在淘宝和拼多多各买了一个这样的,名叫Tiny RTC,2元

反面是这样的,需要手工焊接,不太友好

焊接好之后是这样的,我努力学了很多天,总算是掌握了一项新技能。

下面开始分享我的经验,有以下几个点值得注意:

1、需要手工焊接,这点无法回避,老老实实焊接好5个洞的那头,至少焊接4根,DS那根可以不用,但是既然都能焊接4根了,也不在乎多1根了,我一次性把两头(一头5根,一头7根)都焊接好了;

PS:有人问到:SQ和DS,以及上面还有三个洞洞是干什么用的?

答:三个洞洞是焊接DS18B20温度传感器的,顾名思义DS就是读取温度的引脚了。设计者应该是计划用户做一个天气日历模块的。SQ是方波输出,是square的简称,用作测试调试之用。

2、焊好就是接线了,这里不会有坑,4根线没人会接错的;

3、接下来就是需要一个测试程序了,2块钱买来的地方未必会提供,客服一般都是机器人,这时如果没有一个测试完好的程序,新手就会很迷茫,到底这东西有没有用,下一步不知道从哪里开始着手了。现在不用慌了,以下有一个完整的程序,我测试了100遍以上。硬件上我用的是Arduino UNO R3,由于只有电源正负2根和SCL、SDA2根共4根线,所以硬件连接上不用考虑什么硬件不一致的问题。另外,我还可以提供部分技术支持,尽管留言。到这里就完成一半了,下面一半是代码了;

4、代码的第一个问题可能是你店家带来的声明是不对的,应该使用RTC_DS1307 RTC来定义RTC变量,而不是DS1307 RTC;(RTClib等库是需要的,这个我不再这里赘述)

5、当前时间设置用这句:RTC.adjust(DateTime(2021, 5, 9, 15, 43, 01)); 

6、秒钟肯定不对的,不过不用慌,文末的代码还包括了一点我自己的代码来进行秒钟微调,不过现在不用管这种小事,稍后反注释//#define HACK_ADJUST这句我们再来调整准确的秒钟;

7、程序刷入进去之后,第一个可能遇到的问题就是时间动了,但是每次重启又还是原来的时间。这个问题仔细想想就不难发现,因为我们刚刚刷进去的代码就包括了一个写死的时间呀,那每次启动可不又像第一次来设置时间时一模一样了?这和时光倒流效果一样,对吧 :P

8、所以,一旦成功写入读出时间了,那就再也不需要设置时间这一句了,马上注释掉并再次烧入程序;  //RTC.adjust(DateTime(2021, 5, 9, 15, 43, 01)); //设置初始时间

9、现在程序里没有任何地方可以修改你的时间了,想修改都修改不了了,呵呵,这时不是还有秒针不太对的问题吗,用这句#define HACK_ADJUST打开我写的那段代码功能,修改其中这句中的数字1为合适的值: Wire.write(bin2bcd(sec + 1));  //秒级微调——+1可以改为合适的调整值,不要加太多,避免进位,或者用减法更靠谱。这段代码是我从Wire库和RTClib库里面抽取并修改形成的;

10、这下好像就全完成了,还有一些什么要注意的呢,让我想想。对咯,就是拔线的时候注意不要碰到那个3V锂电池(CR2032),否则时间会变成2000-01-01,不过,这又有什么慌的呢,重做一遍就是了。如果我没有遇到我怎么会知道呢,O(∩_∩)O

#include <Streaming.h>
#include <Wire.h>//IIC库
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

//#define HACK_ADJUST
#ifdef HACK_ADJUST
int adjusted = 0;
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}
#endif

LiquidCrystal_I2C lcd(0x27, 16, 2); //设置LCD1602设备地址0x27
RTC_DS1307 RTC;

void setup()
{
  Wire.begin(); // 开启总线,这个用于I2C的使用
  RTC.begin();  // 初始化时钟
  //RTC.adjust(DateTime(2021, 5, 9, 15, 43, 01)); //设置初始时间
  lcd.init();                  // 初始化LCD
  lcd.backlight();             //设置LCD背景灯亮
  Serial.begin(115200);
}

void loop()
{
  DateTime dateTime = RTC.now(); // 获取现在的时间
  Serial << dateTime.year() << "-" << dateTime.month() << "-" << dateTime.day() << endl;
  Serial << dateTime.hour() << ":" << dateTime.minute() << ":" << dateTime.second() << endl;

  //显示年
  lcd.setCursor(3, 0);
  lcd.print(dateTime.year());

  //显示月
  lcd.print('-');
  if (dateTime.month() > 9)
  {
    lcd.print(dateTime.month());
  }
  else
  {
    lcd.print('0');
    lcd.print(dateTime.month());
  }

  //显示日
  lcd.print('-');
  if (dateTime.day() > 9)
  {
    lcd.print(dateTime.day());
  }
  else
  {
    lcd.print('0');
    lcd.print(dateTime.day());
  }

  //显示小时
  lcd.setCursor(4, 1);
  if (dateTime.hour() > 9)
  {
    lcd.print(dateTime.hour());
  } else
  {
    lcd.print('0');
    lcd.print(dateTime.hour());
  }

  //显示分钟
  lcd.print(':');
  if (dateTime.minute() > 9)
  {
    lcd.print(dateTime.minute());
  }
  else
  {
    lcd.print('0');
    lcd.print(dateTime.minute());
  }

  //显示秒
  lcd.print(':');
  if (dateTime.second() > 9)
  {    
#ifdef HACK_ADJUST    //A hacking adjust by Safirst C. Ke
    int sec = dateTime.second();
    if (!adjusted)
    {
      Wire.beginTransmission(DS1307_ADDRESS);
      Wire.write((byte)0);
      Wire.write(bin2bcd(sec + 1));  //秒级微调——+1可以改为合适的调整值,不要加太多,避免进位,或者用减法更靠谱。
      Wire.endTransmission();
      adjusted = 1;
    }  
#endif

    lcd.print(dateTime.second());
  }
  else
  {
    lcd.print('0');
    lcd.print(dateTime.second());
  }
  delay(990);
}
以下是使用 Arduino 来初始化设置 Tiny RTC 12C 时钟模块的示例代码: ```cpp #include <Wire.h> #define DS1307_ADDRESS 0x68 // I2C address of the DS1307 RTC void setup() { Wire.begin(); // Initialize I2C communication Serial.begin(9600); // Initialize serial communication // Set the time and date on the DS1307 // Format: seconds, minutes, hours, day of the week, day, month, year setTimeDS1307(0, 0, 12, 5, 6, 11, 21); } void loop() { // Read the time from the DS1307 and print it to the serial monitor Serial.print(getHourDS1307()); Serial.print(":"); Serial.print(getMinuteDS1307()); Serial.print(":"); Serial.println(getSecondDS1307()); delay(1000); // Wait for one second } // Function to set the time and date on the DS1307 void setTimeDS1307(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) { Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x00); // Set the register pointer to 00h Wire.write(decToBcd(second)); // Set the seconds Wire.write(decToBcd(minute)); // Set the minutes Wire.write(decToBcd(hour)); // Set the hours Wire.write(decToBcd(dayOfWeek)); // Set the day of the week (1=Sunday, 7=Saturday) Wire.write(decToBcd(dayOfMonth)); // Set the day of the month Wire.write(decToBcd(month)); // Set the month Wire.write(decToBcd(year)); // Set the year (0-99) Wire.endTransmission(); } // Function to get the hour from the DS1307 byte getHourDS1307() { Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x02); // Set the register pointer to 02h Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 1); // Request one byte of data byte hour = bcdToDec(Wire.read() & 0x3f); // Get the hour (0-23) return hour; } // Function to get the minute from the DS1307 byte getMinuteDS1307() { Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x01); // Set the register pointer to 01h Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 1); // Request one byte of data byte minute = bcdToDec(Wire.read()); // Get the minute (0-59) return minute; } // Function to get the second from the DS1307 byte getSecondDS1307() { Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x00); // Set the register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 1); // Request one byte of data byte second = bcdToDec(Wire.read() & 0x7f); // Get the second (0-59) return second; } // Function to convert a decimal number to BCD byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); } // Function to convert a BCD number to decimal byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); } ``` 这个示例代码展示了如何使用 Wire 库来读写 I2C 总线上的数据。首先,我们需要使用 `Wire.begin()` 来初始化 I2C 通信。然后,使用 `setTimeDS1307()` 函数来设置时间和日期。该函数会将当前时间和日期写入到 DS1307 的寄存器中。接下来,在 `loop()` 函数中,我们使用 `getHourDS1307()`、`getMinuteDS1307()` 和 `getSecondDS1307()` 函数来读取当前时间,并将其打印到串口监视器中。最后,我们使用 `delay(1000)` 函数来等待一秒钟,以确保每秒钟只打印一次时间。 请注意,上面的示例代码使用 DS1307 地址为 0x68。如果你使用的是不同的 RTC 时钟模块,可能需要修改地址。同时,你需要在 Arduino 中下载安装 Wire 库。
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

safirst

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值