mirror of
https://github.com/dustinbrun/Binaeruhr-Arduino.git
synced 2026-05-03 17:14:13 +00:00
Upload 1
This commit is contained in:
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
DS3231.cpp - Arduino/chipKit library support for the DS3231 I2C Real-Time Clock
|
||||
Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
|
||||
|
||||
This library has been made to easily interface and use the DS3231 RTC with
|
||||
an Arduino or chipKit.
|
||||
|
||||
You can find the latest version of the library at
|
||||
http://www.RinkyDinkElectronics.com/
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the CC BY-NC-SA 3.0 license.
|
||||
Please see the included documents for further information.
|
||||
|
||||
Commercial use of this library requires you to buy a license that
|
||||
will allow commercial use. This includes using the library,
|
||||
modified or not, as a tool to sell products.
|
||||
|
||||
The license applies to all part of the library including the
|
||||
examples and tools supplied with the library.
|
||||
*/
|
||||
#include "DS3231.h"
|
||||
|
||||
// Include hardware-specific functions for the correct MCU
|
||||
#if defined(__AVR__)
|
||||
#include "hardware/avr/HW_AVR.h"
|
||||
#elif defined(__PIC32MX__)
|
||||
#include "hardware/pic32/HW_PIC32.h"
|
||||
#elif defined(__arm__)
|
||||
#include "hardware/arm/HW_ARM.h"
|
||||
#endif
|
||||
|
||||
#define REG_SEC 0x00
|
||||
#define REG_MIN 0x01
|
||||
#define REG_HOUR 0x02
|
||||
#define REG_DOW 0x03
|
||||
#define REG_DATE 0x04
|
||||
#define REG_MON 0x05
|
||||
#define REG_YEAR 0x06
|
||||
#define REG_CON 0x0e
|
||||
#define REG_STATUS 0x0f
|
||||
#define REG_AGING 0x10
|
||||
#define REG_TEMPM 0x11
|
||||
#define REG_TEMPL 0x12
|
||||
|
||||
#define SEC_1970_TO_2000 946684800
|
||||
|
||||
static const uint8_t dim[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||
|
||||
/* Public */
|
||||
|
||||
Time::Time()
|
||||
{
|
||||
this->year = 2014;
|
||||
this->mon = 1;
|
||||
this->date = 1;
|
||||
this->hour = 0;
|
||||
this->min = 0;
|
||||
this->sec = 0;
|
||||
this->dow = 3;
|
||||
}
|
||||
|
||||
DS3231::DS3231(uint8_t data_pin, uint8_t sclk_pin)
|
||||
{
|
||||
_sda_pin = data_pin;
|
||||
_scl_pin = sclk_pin;
|
||||
}
|
||||
|
||||
Time DS3231::getTime()
|
||||
{
|
||||
Time t;
|
||||
_burstRead();
|
||||
t.sec = _decode(_burstArray[0]);
|
||||
t.min = _decode(_burstArray[1]);
|
||||
t.hour = _decodeH(_burstArray[2]);
|
||||
t.dow = _burstArray[3];
|
||||
t.date = _decode(_burstArray[4]);
|
||||
t.mon = _decode(_burstArray[5]);
|
||||
t.year = _decodeY(_burstArray[6])+2000;
|
||||
return t;
|
||||
}
|
||||
|
||||
void DS3231::setTime(uint8_t hour, uint8_t min, uint8_t sec)
|
||||
{
|
||||
if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)) && ((sec>=0) && (sec<60)))
|
||||
{
|
||||
_writeRegister(REG_HOUR, _encode(hour));
|
||||
_writeRegister(REG_MIN, _encode(min));
|
||||
_writeRegister(REG_SEC, _encode(sec));
|
||||
}
|
||||
}
|
||||
|
||||
void DS3231::setDate(uint8_t date, uint8_t mon, uint16_t year)
|
||||
{
|
||||
if (((date>0) && (date<=31)) && ((mon>0) && (mon<=12)) && ((year>=2000) && (year<3000)))
|
||||
{
|
||||
year -= 2000;
|
||||
_writeRegister(REG_YEAR, _encode(year));
|
||||
_writeRegister(REG_MON, _encode(mon));
|
||||
_writeRegister(REG_DATE, _encode(date));
|
||||
}
|
||||
}
|
||||
|
||||
void DS3231::setDOW()
|
||||
{
|
||||
int dow;
|
||||
byte mArr[12] = {6,2,2,5,0,3,5,1,4,6,2,4};
|
||||
Time _t = getTime();
|
||||
|
||||
dow = (_t.year % 100);
|
||||
dow = dow*1.25;
|
||||
dow += _t.date;
|
||||
dow += mArr[_t.mon-1];
|
||||
if (((_t.year % 4)==0) && (_t.mon<3))
|
||||
dow -= 1;
|
||||
while (dow>7)
|
||||
dow -= 7;
|
||||
_writeRegister(REG_DOW, dow);
|
||||
}
|
||||
|
||||
void DS3231::setDOW(uint8_t dow)
|
||||
{
|
||||
if ((dow>0) && (dow<8))
|
||||
_writeRegister(REG_DOW, dow);
|
||||
}
|
||||
|
||||
char *DS3231::getTimeStr(uint8_t format)
|
||||
{
|
||||
static char output[] = "xxxxxxxx";
|
||||
Time t;
|
||||
t=getTime();
|
||||
if (t.hour<10)
|
||||
output[0]=48;
|
||||
else
|
||||
output[0]=char((t.hour / 10)+48);
|
||||
output[1]=char((t.hour % 10)+48);
|
||||
output[2]=58;
|
||||
if (t.min<10)
|
||||
output[3]=48;
|
||||
else
|
||||
output[3]=char((t.min / 10)+48);
|
||||
output[4]=char((t.min % 10)+48);
|
||||
output[5]=58;
|
||||
if (format==FORMAT_SHORT)
|
||||
output[5]=0;
|
||||
else
|
||||
{
|
||||
if (t.sec<10)
|
||||
output[6]=48;
|
||||
else
|
||||
output[6]=char((t.sec / 10)+48);
|
||||
output[7]=char((t.sec % 10)+48);
|
||||
output[8]=0;
|
||||
}
|
||||
return (char*)&output;
|
||||
}
|
||||
|
||||
char *DS3231::getDateStr(uint8_t slformat, uint8_t eformat, char divider)
|
||||
{
|
||||
static char output[] = "xxxxxxxxxx";
|
||||
int yr, offset;
|
||||
Time t;
|
||||
t=getTime();
|
||||
switch (eformat)
|
||||
{
|
||||
case FORMAT_LITTLEENDIAN:
|
||||
if (t.date<10)
|
||||
output[0]=48;
|
||||
else
|
||||
output[0]=char((t.date / 10)+48);
|
||||
output[1]=char((t.date % 10)+48);
|
||||
output[2]=divider;
|
||||
if (t.mon<10)
|
||||
output[3]=48;
|
||||
else
|
||||
output[3]=char((t.mon / 10)+48);
|
||||
output[4]=char((t.mon % 10)+48);
|
||||
output[5]=divider;
|
||||
if (slformat==FORMAT_SHORT)
|
||||
{
|
||||
yr=t.year-2000;
|
||||
if (yr<10)
|
||||
output[6]=48;
|
||||
else
|
||||
output[6]=char((yr / 10)+48);
|
||||
output[7]=char((yr % 10)+48);
|
||||
output[8]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
yr=t.year;
|
||||
output[6]=char((yr / 1000)+48);
|
||||
output[7]=char(((yr % 1000) / 100)+48);
|
||||
output[8]=char(((yr % 100) / 10)+48);
|
||||
output[9]=char((yr % 10)+48);
|
||||
output[10]=0;
|
||||
}
|
||||
break;
|
||||
case FORMAT_BIGENDIAN:
|
||||
if (slformat==FORMAT_SHORT)
|
||||
offset=0;
|
||||
else
|
||||
offset=2;
|
||||
if (slformat==FORMAT_SHORT)
|
||||
{
|
||||
yr=t.year-2000;
|
||||
if (yr<10)
|
||||
output[0]=48;
|
||||
else
|
||||
output[0]=char((yr / 10)+48);
|
||||
output[1]=char((yr % 10)+48);
|
||||
output[2]=divider;
|
||||
}
|
||||
else
|
||||
{
|
||||
yr=t.year;
|
||||
output[0]=char((yr / 1000)+48);
|
||||
output[1]=char(((yr % 1000) / 100)+48);
|
||||
output[2]=char(((yr % 100) / 10)+48);
|
||||
output[3]=char((yr % 10)+48);
|
||||
output[4]=divider;
|
||||
}
|
||||
if (t.mon<10)
|
||||
output[3+offset]=48;
|
||||
else
|
||||
output[3+offset]=char((t.mon / 10)+48);
|
||||
output[4+offset]=char((t.mon % 10)+48);
|
||||
output[5+offset]=divider;
|
||||
if (t.date<10)
|
||||
output[6+offset]=48;
|
||||
else
|
||||
output[6+offset]=char((t.date / 10)+48);
|
||||
output[7+offset]=char((t.date % 10)+48);
|
||||
output[8+offset]=0;
|
||||
break;
|
||||
case FORMAT_MIDDLEENDIAN:
|
||||
if (t.mon<10)
|
||||
output[0]=48;
|
||||
else
|
||||
output[0]=char((t.mon / 10)+48);
|
||||
output[1]=char((t.mon % 10)+48);
|
||||
output[2]=divider;
|
||||
if (t.date<10)
|
||||
output[3]=48;
|
||||
else
|
||||
output[3]=char((t.date / 10)+48);
|
||||
output[4]=char((t.date % 10)+48);
|
||||
output[5]=divider;
|
||||
if (slformat==FORMAT_SHORT)
|
||||
{
|
||||
yr=t.year-2000;
|
||||
if (yr<10)
|
||||
output[6]=48;
|
||||
else
|
||||
output[6]=char((yr / 10)+48);
|
||||
output[7]=char((yr % 10)+48);
|
||||
output[8]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
yr=t.year;
|
||||
output[6]=char((yr / 1000)+48);
|
||||
output[7]=char(((yr % 1000) / 100)+48);
|
||||
output[8]=char(((yr % 100) / 10)+48);
|
||||
output[9]=char((yr % 10)+48);
|
||||
output[10]=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (char*)&output;
|
||||
}
|
||||
|
||||
char *DS3231::getDOWStr(uint8_t format)
|
||||
{
|
||||
char *output = "xxxxxxxxxx";
|
||||
char *daysLong[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
|
||||
char *daysShort[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
||||
Time t;
|
||||
t=getTime();
|
||||
if (format == FORMAT_SHORT)
|
||||
output = daysShort[t.dow-1];
|
||||
else
|
||||
output = daysLong[t.dow-1];
|
||||
return output;
|
||||
}
|
||||
|
||||
char *DS3231::getMonthStr(uint8_t format)
|
||||
{
|
||||
char *output= "xxxxxxxxx";
|
||||
char *monthLong[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||
char *monthShort[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
Time t;
|
||||
t=getTime();
|
||||
if (format == FORMAT_SHORT)
|
||||
output = monthShort[t.mon-1];
|
||||
else
|
||||
output = monthLong[t.mon-1];
|
||||
return output;
|
||||
}
|
||||
|
||||
long DS3231::getUnixTime(Time t)
|
||||
{
|
||||
uint16_t dc;
|
||||
|
||||
dc = t.date;
|
||||
for (uint8_t i = 0; i<(t.mon-1); i++)
|
||||
dc += dim[i];
|
||||
if ((t.mon > 2) && (((t.year-2000) % 4) == 0))
|
||||
++dc;
|
||||
dc = dc + (365 * (t.year-2000)) + (((t.year-2000) + 3) / 4) - 1;
|
||||
|
||||
return ((((((dc * 24L) + t.hour) * 60) + t.min) * 60) + t.sec) + SEC_1970_TO_2000;
|
||||
|
||||
}
|
||||
|
||||
void DS3231::enable32KHz(bool enable)
|
||||
{
|
||||
uint8_t _reg = _readRegister(REG_STATUS);
|
||||
_reg &= ~(1 << 3);
|
||||
_reg |= (enable << 3);
|
||||
_writeRegister(REG_STATUS, _reg);
|
||||
}
|
||||
|
||||
void DS3231::setOutput(byte enable)
|
||||
{
|
||||
uint8_t _reg = _readRegister(REG_CON);
|
||||
_reg &= ~(1 << 2);
|
||||
_reg |= (enable << 2);
|
||||
_writeRegister(REG_CON, _reg);
|
||||
}
|
||||
|
||||
void DS3231::setSQWRate(int rate)
|
||||
{
|
||||
uint8_t _reg = _readRegister(REG_CON);
|
||||
_reg &= ~(3 << 3);
|
||||
_reg |= (rate << 3);
|
||||
_writeRegister(REG_CON, _reg);
|
||||
}
|
||||
|
||||
float DS3231::getTemp()
|
||||
{
|
||||
uint8_t _msb = _readRegister(REG_TEMPM);
|
||||
uint8_t _lsb = _readRegister(REG_TEMPL);
|
||||
return (float)_msb + ((_lsb >> 6) * 0.25f);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
void DS3231::_sendStart(byte addr)
|
||||
{
|
||||
pinMode(_sda_pin, OUTPUT);
|
||||
digitalWrite(_sda_pin, HIGH);
|
||||
digitalWrite(_scl_pin, HIGH);
|
||||
digitalWrite(_sda_pin, LOW);
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
shiftOut(_sda_pin, _scl_pin, MSBFIRST, addr);
|
||||
}
|
||||
|
||||
void DS3231::_sendStop()
|
||||
{
|
||||
pinMode(_sda_pin, OUTPUT);
|
||||
digitalWrite(_sda_pin, LOW);
|
||||
digitalWrite(_scl_pin, HIGH);
|
||||
digitalWrite(_sda_pin, HIGH);
|
||||
pinMode(_sda_pin, INPUT);
|
||||
}
|
||||
|
||||
void DS3231::_sendNack()
|
||||
{
|
||||
pinMode(_sda_pin, OUTPUT);
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
digitalWrite(_sda_pin, HIGH);
|
||||
digitalWrite(_scl_pin, HIGH);
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
pinMode(_sda_pin, INPUT);
|
||||
}
|
||||
|
||||
void DS3231::_sendAck()
|
||||
{
|
||||
pinMode(_sda_pin, OUTPUT);
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
digitalWrite(_sda_pin, LOW);
|
||||
digitalWrite(_scl_pin, HIGH);
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
pinMode(_sda_pin, INPUT);
|
||||
}
|
||||
|
||||
void DS3231::_waitForAck()
|
||||
{
|
||||
pinMode(_sda_pin, INPUT);
|
||||
digitalWrite(_scl_pin, HIGH);
|
||||
while (digitalRead(_sda_pin)==HIGH) {}
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
}
|
||||
|
||||
uint8_t DS3231::_readByte()
|
||||
{
|
||||
pinMode(_sda_pin, INPUT);
|
||||
|
||||
uint8_t value = 0;
|
||||
uint8_t currentBit = 0;
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
digitalWrite(_scl_pin, HIGH);
|
||||
currentBit = digitalRead(_sda_pin);
|
||||
value |= (currentBit << 7-i);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(_scl_pin, LOW);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void DS3231::_writeByte(uint8_t value)
|
||||
{
|
||||
pinMode(_sda_pin, OUTPUT);
|
||||
shiftOut(_sda_pin, _scl_pin, MSBFIRST, value);
|
||||
}
|
||||
|
||||
uint8_t DS3231::_decode(uint8_t value)
|
||||
{
|
||||
uint8_t decoded = value & 127;
|
||||
decoded = (decoded & 15) + 10 * ((decoded & (15 << 4)) >> 4);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
uint8_t DS3231::_decodeH(uint8_t value)
|
||||
{
|
||||
if (value & 128)
|
||||
value = (value & 15) + (12 * ((value & 32) >> 5));
|
||||
else
|
||||
value = (value & 15) + (10 * ((value & 48) >> 4));
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t DS3231::_decodeY(uint8_t value)
|
||||
{
|
||||
uint8_t decoded = (value & 15) + 10 * ((value & (15 << 4)) >> 4);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
uint8_t DS3231::_encode(uint8_t value)
|
||||
{
|
||||
uint8_t encoded = ((value / 10) << 4) + (value % 10);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user