分享一个RX8025T时钟芯片的Arduino代码

分享一个RX8025T时钟芯片的Arduino代码

背景

之前做那个点阵时钟使用的是DS3231的时钟芯片,这个时钟芯片最大的有点就是高精度,缺点就是有点贵,现在淘宝一颗这样的芯片最便宜的都要十几块钱,大大的增加了我整个点阵时钟的成本造价,所以不得已采用了这个新的时钟芯片方案,就是RX8025T,成本大概就是一块钱左右。

RX8025芯片介绍

1.内置高稳定度的32.768KHz 的 DTCXO (数字温度补偿晶体振荡器)

  1. 支持I2C总线的高速模式(400K)。
  2. 定时报警功能(可设定:天,日期,小时,分钟)
  3. 固定周期定时中断功能。
  4. 时间更新中断功能。
  5. 32.768KHz频率输出(具有使能OE功能)
  6. 闰年自动调整功能。(2000到2099)
  7. 宽范围接口电压:2.2V到5.5V
  8. 宽范围的时间保持电压:1.8V到5.5V10.低电流功耗:0.8uA/3V (Typ.)
相关文档

更多的介绍看下面的文档,如果文档失效的话,请百度搜索关键字RX-8025T使用说明概要

RX-8025T使用说明概要

电路&PCB设计

其实很早就想搞这个RX8025T的时钟芯片了,但是无奈淘宝上没有现成的模块,所以就只能自己搞一个了,然后就百度各种原理图,发现大家的原理图就都不太一样,所以就综合各种原理图搞一个大概的原理图出来,然后画一个简单的PCB板出来搞一搞,所以原理图这块仅供学习和参考,如果有大佬有更好的方案欢迎在评论区指出。

立创开源地址

RX8025T模块(附Arduino代码)

RX8025T电路原理图

RX8025T电路原理图

PCB-3D预览图

PCB-3D预览图

成品图

成品图

Arduino代码

目前由于我还只擅长Arduino平台的代码处理,所以就只贴出来Arduino的代码,后续如果有其他平台的代码,一定也会在这里列举出来。由于RX8025T主要采用的是I2C通讯协议,且ArduinoI2C的实现较为简单,所以代码也很容易看懂,这里更多的像是搬运别人的代码吧,首先是在网上看到有一段关于8025arduino代码,然后又结合DS3231的代码,由此缝合出来了这段我个人觉得还能用的RX8025T代码。下面列出参考地址:

  • DS3231库源码地址:https://github.com/NorthernWidget/DS3231
  • RX8025参考代码地址:RX8025 library updated for IDE 1.0
  • I2C通讯协议学习地址:RX-8025T使用说明概要

RX8025.h

#ifndef RX8025_h
#define RX8025_h

#define RX8025_SEC 0x0
#define RX8025_MIN 0x1
#define RX8025_HR 0x2
#define RX8025_WEEK 0x3
#define RX8025_DATE 0x4
#define RX8025_MTH 0x5
#define RX8025_YR 0x6
#define RX8025_Doffset 0x7
#define RX8025_AW_MIN 0x8
#define RX8025_AW_HR 0x9
#define RX8025_AW_WEEK 0xa
#define RX8025_AD_MIN 0xb
#define RX8025_AD_HR 0xc
#define RX8025_CTL1 0xd
#define RX8025_CTL2 0xE

#include 
#include 
#include 
// DateTime (get everything at once) from JeeLabs / Adafruit
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
class DateTime
{
public:
  DateTime(uint32_t t = 0);
  DateTime(uint16_t year, uint8_t month, uint8_t day,
           uint8_t hour = 0, uint8_t min = 0, uint8_t sec = 0);
  DateTime(const char *date, const char *time);
  uint16_t year() const
  {
    return 2000 + yOff;
  }
  uint8_t month() const
  {
    return m;
  }
  uint8_t day() const
  {
    return d;
  }
  uint8_t hour() const
  {
    return hh;
  }
  uint8_t minute() const
  {
    return mm;
  }
  uint8_t second() const
  {
    return ss;
  }
  uint8_t dayOfTheWeek() const;

  // 32-bit times as seconds since 1/1/2000
  long secondstime() const;
  // 32-bit times as seconds since 1/1/1970
  // THE ABOVE COMMENT IS CORRECT FOR LOCAL TIME; TO USE THIS COMMAND TO
  // OBTAIN TRUE UNIX TIME SINCE EPOCH, YOU MUST CALL THIS COMMAND AFTER
  // SETTING YOUR CLOCK TO UTC
  uint32_t unixtime(void) const;

protected:
  uint8_t yOff, m, d, hh, mm, ss;
};

//判断年份是否是闰年
bool isleapYear(const uint8_t);

class RX8025
{
private:
  unsigned char RX8025_Control[2];
  /**
   * 获取寄存器数据
   * @return byte
   */
  byte getData(byte regaddr);

  /**
   * @brief 将十进制编码的二进制数转换为普通十进制数
   *
   * @param val
   * @return byte
   */
  byte decToBcd(byte val);

  /**
   * 将二进制编码的十进制数转换为普通十进制数
   * @param val
   * @return byte
   */
  byte bcdToDec(byte val);

public:
  RX8025(); // costruttore
  /**
   * 初始化
   */
  void RX8025_init(void);

  /**
   * 向时钟芯片设置时间
   * @param s  秒钟
   * @param m  分钟
   * @param h 时钟
   * @param d  天
   * @param mh 月
   * @param y 年
   */
  void setRtcTime(uint8_t s, uint8_t m, uint8_t h, uint8_t d, uint8_t mh, uint8_t y);

  /**
   * 获取秒钟
   */
  byte getSecond();
  /**
   * 获取分钟数
   * @return byte
   */
  byte getMinute();
  /**
   * 获取小时数
   * @return byte
   */
  byte getHour();
  /**
   * 获取星期数
   * @return byte
   */
  byte getDoW();
  /**
   * 获取日期
   * @return byte
   */
  byte getDate();
  /**
   * 获取月份
   * @return byte
   */
  byte getMonth();
  /**
   * 获取年份
   * @return byte
   */
  byte getYear();

  /**
   * 获取时间戳
   * @return long
   */
  long getUnixtime();
};

#endif

RX8025.cpp


#include "RX8025.h"
// These included for the DateTime class inclusion; will try to find a way to
// not need them in the future...
#if defined(__AVR__)
#include 
#elif defined(ESP8266)
#include 
#endif
// Changed the following to work on 1.0
//#include "WProgram.h"
#include 

// 8025I2C地址
#define RX8025_address 0x32
// 日期起始时间(这里为啥要减掉八个小时,因为用的日期所在时区和国内时区相差8小时,所以需要减掉八小时的时区时间)
#define SECONDS_FROM_1970_TO_2000 946684800 - (8 * 60 * 60)
//
static const uint8_t daysInMonth[] PROGMEM = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

/**
   自2000/01/01起的天数,2001年有效。。2099
*/
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d)
{
  if (y >= 2000)
    y -= 2000;
  uint16_t days = d;
  for (uint8_t i = 1; i < m; ++i)
    days += pgm_read_byte(daysInMonth + i - 1);
  if (m > 2 && isleapYear(y))
    ++days;
  return days + 365 * y + (y + 3) / 4 - 1;
}

static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s)
{
  return ((days * 24L + h) * 60 + m) * 60 + s;
}

DateTime::DateTime(uint32_t t)
{
  t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970

  ss = t % 60;
  t /= 60;
  mm = t % 60;
  t /= 60;
  hh = t % 24;
  uint16_t days = t / 24;
  uint8_t leap;
  for (yOff = 0;; ++yOff)
  {
    leap = isleapYear(yOff);
    if (days < 365 + leap)
      break;
    days -= 365 + leap;
  }
  for (m = 1;; ++m)
  {
    uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
    if (leap && m == 2)
      ++daysPerMonth;
    if (days < daysPerMonth)
      break;
    days -= daysPerMonth;
  }
  d = days + 1;
}

DateTime::DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
{
  if (year >= 2000)
  {
    year -= 2000;
  }
  yOff = year;
  m = month;
  d = day;
  hh = hour;
  mm = min;
  ss = sec;
}

// supported formats are date "Mmm dd yyyy" and time "hh:mm:ss" (same as __DATE__ and __TIME__)
DateTime::DateTime(const char *date, const char *time)
{
  static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  static char buff[4] = {'0', '0', '0', '0'};
  int y;
  sscanf(date, "%s %c %d", buff, &d, &y);
  yOff = y >= 2000 ? y - 2000 : y;
  m = (strstr(month_names, buff) - month_names) / 3 + 1;
  sscanf(time, "%c:%c:%c", &hh, &mm, &ss);
}

// UNIX time: IS CORRECT ONLY WHEN SET TO UTC!!!
uint32_t DateTime::unixtime(void) const
{
  uint32_t t;
  uint16_t days = date2days(yOff, m, d);
  t = time2long(days, hh, mm, ss);
  t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
  return t;
}

// Slightly modified from JeeLabs / Ladyada
// Get all date/time at once to avoid rollover (e.g., minute/second don't match)
static uint8_t bcd2bin(uint8_t val)
{
  return val - 6 * (val >> 4);
}
// Commented to avoid compiler warnings, but keeping in case we want this
// eventually
static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); }

/**
   判断是否是闰年
*/
bool isleapYear(const uint8_t y)
{
  //检查是否可以被4整除
  if (y & 3)
  {
    return false;
  }
  // 仅在第一次失败时检查其他
  return (y % 100 || y % 400 == 0);
}

RX8025::RX8025() // costruttore
{
  RX8025_Control[0] = 0x20;
  RX8025_Control[1] = 0x00;
}

/**
 * 向时钟芯片设置时间
 * @param s  秒钟
 * @param m  分钟
 * @param h 时钟
 * @param d  天
 * @param mh 月
 * @param y 年
 */
void RX8025::setRtcTime(uint8_t s, uint8_t m, uint8_t h, uint8_t d, uint8_t mh, uint8_t y)
{
  // 使用指定的地址开始向I2C从设备进行传输。
  Wire.beginTransmission(RX8025_address);
  Wire.write((byte)0x00);
  Wire.write(decToBcd(s));
  Wire.write(decToBcd(m));
  Wire.write(decToBcd(h));
  Wire.write(0x1);
  Wire.write(decToBcd(d));
  Wire.write(decToBcd(mh));
  Wire.write(decToBcd(y));
  // 停止与从机的数据传输
  Wire.endTransmission();
}

/**
 * 获取寄存器里面的数据
 * @param regaddr
 * @return byte
 */
byte RX8025::getData(byte regaddr)
{
  // 使用指定的地址开始向I2C从设备进行传输。
  Wire.beginTransmission(RX8025_address);
  Wire.write(regaddr);
  // 停止与从机的数据传输
  Wire.endTransmission();
  // 由主设备用来向从设备请求字节。
  Wire.requestFrom(RX8025_address, 1);
  // 读取数据
  return Wire.read();
}

/**
 * @brief 初始化函数
 *
 */
void RX8025::RX8025_init(void)
{
  // Wire初始化
  Wire.begin();
  // 使用指定的地址开始向I2C从设备进行传输。
  Wire.beginTransmission(RX8025_address);
  Wire.write(0xe0);
  for (unsigned char i = 0; i < 2; i++)
  {
    Wire.write(RX8025_Control[i]);
  }
  // 使用指定的地址开始向I2C从设备进行传输。
  Wire.endTransmission();
}

/**
 * @brief 将十进制编码的二进制数转换为普通十进制数
 *
 * @param val
 * @return byte
 */
byte RX8025::decToBcd(byte val)
{
  // 将十进制编码的二进制数转换为普通十进制数
  return ((val / 10 * 16) + (val % 10));
}

/**
 * 将二进制编码的十进制数转换为普通十进制数
 *
 * @param val
 * @return byte
 */
byte RX8025::bcdToDec(byte val)
{
  // 将二进制编码的十进制数转换为普通十进制数
  return ((val / 16 * 10) + (val % 16));
}

/**
 * 获取秒钟
 */
byte RX8025::getSecond()
{
  byte buff = getData(RX8025_SEC);
  return bcdToDec(buff & 0x7f);
}

/**
 * 获取分钟数
 * @return byte
 */
byte RX8025::getMinute()
{
  byte buff = getData(RX8025_MIN);
  return bcdToDec(buff & 0x7f);
}

/**
 * 获取小时数
 * @return byte
 */
byte RX8025::getHour()
{
  byte buff = getData(RX8025_HR);
  return bcdToDec(buff & 0x3f);
}

/**
 * 获取星期数
 * @return byte
 */
byte RX8025::getDoW()
{
  byte buff = getData(RX8025_WEEK);
  return bcdToDec(buff & 0x07);
}

/**
 * 获取日期
 * @return byte
 */
byte RX8025::getDate()
{
  byte buff = getData(RX8025_DATE);
  return bcdToDec(buff & 0x3f);
}

/**
 * 获取月份
 * @return byte
 */
byte RX8025::getMonth()
{
  byte buff = getData(RX8025_MTH);
  return bcdToDec(buff & 0x1f);
}

/**
 * 获取年份
 * @return byte
 */
byte RX8025::getYear()
{
  byte buff = getData(RX8025_YR);
  return bcdToDec(buff & 0xff);
}

long RX8025::getUnixtime()
{
  // 使用指定的地址开始向I2C从设备进行传输。
  Wire.beginTransmission(RX8025_address);
  Wire.write(0x00);
  // 停止与从机的数据传输
  Wire.endTransmission();
  // 由主设备用来向从设备请求字节。
  Wire.requestFrom(RX8025_address, 7);
  // 读取数据
  uint16_t ss = bcdToDec(Wire.read() & 0x7F);
  uint16_t mm = bcdToDec(Wire.read() & 0x7f);
  uint16_t hh = bcdToDec(Wire.read() & 0x3f);
  Wire.read();
  uint16_t d = bcdToDec(Wire.read() & 0x3f);
  uint16_t m = bcdToDec(Wire.read() & 0x1f);
  uint16_t y = bcdToDec(Wire.read() & 0xff) + 2000;
  return DateTime(y, m, d, hh, mm, ss).unixtime();
}

主函数

#include "Arduino.h"
#include "RX8025.h"

RX8025 rtc;
DateTime datetime;

void setup(void)
{
  Serial.begin(9600);
  Serial.println("on the setup");
  rtc.RX8025_init();
  rtc.setRtcTime(0, 24, 21, 4, 4, 22);
}

void loop(void)
{
  Serial.print(rtc.getYear());
  Serial.print("年");
  Serial.print(rtc.getMonth());
  Serial.print("月");
  Serial.print(rtc.getDate());
  Serial.print("日");
  Serial.print(rtc.getHour());
  Serial.print(":");
  Serial.print(rtc.getMinute());
  Serial.print(":");
  Serial.println(rtc.getSecond());
  delay(1000);
  Serial.println(rtc.getUnixtime());
}

参考文章

I2C详解

太极创客 - Arduino – Wire 库

RX-8025T使用说明概要

RX8025 library updated for IDE 1.0

你可能感兴趣的:(分享一个RX8025T时钟芯片的Arduino代码)