RTCModuleDS1302 and LCDI2C16x02 (A0, A1, A2 Not Soldered-without a Bridge)
by ngrigoriev in Circuits > Arduino
2380 Views, 12 Favorites, 0 Comments
RTCModuleDS1302 and LCDI2C16x02 (A0, A1, A2 Not Soldered-without a Bridge)
Hello. Recently I bought a cheap version of RTCModule DS1302 and I didn't find a lot of info how to fix it to Arduino board. I also have an LCD screen I2C 16x2. So I decided to display the data on it.
Library DS1302.h
/*
DS1302.h - Arduino library support for the DS1302 Trickle Charge Timekeeping Chip
Copyright (C)2010 Henning Karlsen. All right reserved
You can find the latest version of the library at
http://www.henningkarlsen.com/electronics
This library has been made to easily interface and use the DS1302 RTC with
the Arduino.
If you make any modifications or improvements to the code, I would appreciate
that you share the code with me so that I might include it in the next release.
I can be contacted through http://www.henningkarlsen.com/electronics/contact.php
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DS1302_h
#define DS1302_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define FORMAT_SHORT 1
#define FORMAT_LONG 2
#define FORMAT_LITTLEENDIAN 1
#define FORMAT_BIGENDIAN 2
#define FORMAT_MIDDLEENDIAN 3
#define MONDAY 1
#define TUESDAY 2
#define WEDNESDAY 3
#define THURSDAY 4
#define FRIDAY 5
#define SATURDAY 6
#define SUNDAY 7
#define TCR_D1R2K 165
#define TCR_D1R4K 166
#define TCR_D1R8K 167
#define TCR_D2R2K 169
#define TCR_D2R4K 170
#define TCR_D2R8K 171
#define TCR_OFF 92
class Time
{
public:
uint8_t hour;
uint8_t min;
uint8_t sec;
uint8_t date;
uint8_t mon;
uint16_t year;
uint8_t dow;
Time();
};
class DS1302_RAM
{
public:
byte cell[31];
DS1302_RAM();
};
class DS1302
{
public:
DS1302(uint8_t ce_pin, uint8_t data_pin, uint8_t sclk_pin);
Time getTime();
void setTime(uint8_t hour, uint8_t min, uint8_t sec);
void setDate(uint8_t date, uint8_t mon, uint16_t year);
void setDOW(uint8_t dow);
char *getTimeStr(uint8_t format=FORMAT_LONG);
char *getDateStr(uint8_t slformat=FORMAT_LONG, uint8_t eformat=FORMAT_LITTLEENDIAN, char divider='.');
char *getDOWStr(uint8_t format=FORMAT_LONG);
char *getMonthStr(uint8_t format=FORMAT_LONG);
void halt(bool value);
void writeProtect(bool enable);
void setTCR(uint8_t value);
void writeBuffer(DS1302_RAM r);
DS1302_RAM readBuffer();
void poke(uint8_t addr, uint8_t value);
uint8_t peek(uint8_t addr);
private:
uint8_t _ce_pin;
uint8_t _data_pin;
uint8_t _sclk_pin;
uint8_t _burstArray[8];
uint8_t _readByte();
void _writeByte(uint8_t value);
uint8_t _readRegister(uint8_t reg);
void _writeRegister(uint8_t reg, uint8_t value);
void _burstRead();
uint8_t _decode(uint8_t value);
uint8_t _decodeH(uint8_t value);
uint8_t _decodeY(uint8_t value);
uint8_t _encode(uint8_t vaule);
};
#endif
Library DS1302.cpp
/*
DS1302.cpp - Arduino library support for the DS1302 Trickle Charge Timekeeping Chip
Copyright (C)2010 Henning Karlsen. All right reserved
You can find the latest version of the library at
http://www.henningkarlsen.com/electronics
This library has been made to easily interface and use the DS1302 RTC with
the Arduino.
If you make any modifications or improvements to the code, I would appreciate
that you share the code with me so that I might include it in the next release.
I can be contacted through http://www.henningkarlsen.com/electronics/contact.php
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "DS1302.h"
#define REG_SEC 0
#define REG_MIN 1
#define REG_HOUR 2
#define REG_DATE 3
#define REG_MON 4
#define REG_DOW 5
#define REG_YEAR 6
#define REG_WP 7
#define REG_TCR 8
/* Public */
Time::Time()
{
this->year = 2010;
this->mon = 1;
this->date = 1;
this->hour = 0;
this->min = 0;
this->sec = 0;
this->dow = 5;
}
DS1302_RAM::DS1302_RAM()
{
for (int i=0; i<31; i++)
cell[i]=0;
}
DS1302::DS1302(uint8_t ce_pin, uint8_t data_pin, uint8_t sclk_pin)
{
_ce_pin = ce_pin;
_data_pin = data_pin;
_sclk_pin = sclk_pin;
pinMode(_ce_pin, OUTPUT);
pinMode(_sclk_pin, OUTPUT);
}
Time DS1302::getTime()
{
Time t;
_burstRead();
t.sec = _decode(_burstArray[0]);
t.min = _decode(_burstArray[1]);
t.hour = _decodeH(_burstArray[2]);
t.date = _decode(_burstArray[3]);
t.mon = _decode(_burstArray[4]);
t.dow = _burstArray[5];
t.year = _decodeY(_burstArray[6])+2000;
return t;
}
void DS1302::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 DS1302::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 DS1302::setDOW(uint8_t dow)
{
if ((dow>0) && (dow<8))
_writeRegister(REG_DOW, dow);
}
char *DS1302::getTimeStr(uint8_t format)
{
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 output;
}
char *DS1302::getDateStr(uint8_t slformat, uint8_t eformat, char divider)
{
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 output;
}
char *DS1302::getDOWStr(uint8_t format)
{
char *output= "xxxxxxxxx";
Time t;
t=getTime();
switch (t.dow)
{
case MONDAY:
output="Monday";
break;
case TUESDAY:
output="Tuesday";
break;
case WEDNESDAY:
output="Wednesday";
break;
case THURSDAY:
output="Thursday";
break;
case FRIDAY:
output="Friday";
break;
case SATURDAY:
output="Saturday";
break;
case SUNDAY:
output="Sunday";
break;
}
if (format==FORMAT_SHORT)
output[3]=0;
return output;
}
char *DS1302::getMonthStr(uint8_t format)
{
char *output= "xxxxxxxxx";
Time t;
t=getTime();
switch (t.mon)
{
case 1:
output="January";
break;
case 2:
output="February";
break;
case 3:
output="March";
break;
case 4:
output="April";
break;
case 5:
output="May";
break;
case 6:
output="June";
break;
case 7:
output="July";
break;
case 8:
output="August";
break;
case 9:
output="September";
break;
case 10:
output="October";
break;
case 11:
output="November";
break;
case 12:
output="December";
break;
}
if (format==FORMAT_SHORT)
output[3]=0;
return output;
}
void DS1302::halt(bool enable)
{
uint8_t _reg = _readRegister(REG_SEC);
_reg &= ~(1 << 7);
_reg |= (enable << 7);
_writeRegister(REG_SEC, _reg);
}
void DS1302::writeProtect(bool enable)
{
uint8_t _reg = (enable << 7);
_writeRegister(REG_WP, _reg);
}
void DS1302::setTCR(uint8_t value)
{
_writeRegister(REG_TCR, value);
}
/* Private */
uint8_t DS1302::_readByte()
{
pinMode(_data_pin, INPUT);
uint8_t value = 0;
uint8_t currentBit = 0;
for (int i = 0; i < 8; ++i)
{
currentBit = digitalRead(_data_pin);
value |= (currentBit << i);
digitalWrite(_sclk_pin, HIGH);
delayMicroseconds(1);
digitalWrite(_sclk_pin, LOW);
}
return value;
}
void DS1302::_writeByte(uint8_t value)
{
pinMode(_data_pin, OUTPUT);
shiftOut(_data_pin, _sclk_pin, LSBFIRST, value);
}
uint8_t DS1302::_readRegister(uint8_t reg)
{
uint8_t cmdByte = 129;
cmdByte |= (reg << 1);
uint8_t readValue;
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(cmdByte);
readValue = _readByte();
digitalWrite(_ce_pin, LOW);
return readValue;
}
void DS1302::_writeRegister(uint8_t reg, uint8_t value)
{
uint8_t cmdByte = (128 | (reg << 1));
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(cmdByte);
_writeByte(value);
digitalWrite(_ce_pin, LOW);
}
void DS1302::_burstRead()
{
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(191);
for (int i=0; i<8; i++)
{
_burstArray[i] = _readByte();
}
digitalWrite(_ce_pin, LOW);
}
uint8_t DS1302::_decode(uint8_t value)
{
uint8_t decoded = value & 127;
decoded = (decoded & 15) + 10 * ((decoded & (15 << 4)) >> 4);
return decoded;
}
uint8_t DS1302::_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 DS1302::_decodeY(uint8_t value)
{
uint8_t decoded = (value & 15) + 10 * ((value & (15 << 4)) >> 4);
return decoded;
}
uint8_t DS1302::_encode(uint8_t value)
{
uint8_t encoded = ((value / 10) << 4) + (value % 10);
return encoded;
}
void DS1302::writeBuffer(DS1302_RAM r)
{
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(254);
for (int i=0; i<31; i++)
{
_writeByte(r.cell[i]);
}
digitalWrite(_ce_pin, LOW);
}
DS1302_RAM DS1302::readBuffer()
{
DS1302_RAM r;
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(255);
for (int i=0; i<31; i++)
{
r.cell[i] = _readByte();
}
digitalWrite(_ce_pin, LOW);
return r;
}
void DS1302::poke(uint8_t addr, uint8_t value)
{
if ((addr >=0) && (addr<=30))
{
addr = (addr * 2) + 192;
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(addr);
_writeByte(value);
digitalWrite(_ce_pin, LOW);
}
}
uint8_t DS1302::peek(uint8_t addr)
{
if ((addr >=0) && (addr<=30))
{
addr = (addr * 2) + 193;
uint8_t readValue;
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_writeByte(addr);
readValue = _readByte();
digitalWrite(_ce_pin, LOW);
return readValue;
}
else
return 0;
}
Sketch Exemples for RTCModule DS1302
Source: "https://yadi.sk/d/xMK-iHMeWzgQ8"
You need just change the current date.
Connect RTCModule to Arduino Board
RTC Module pins____________Arduino board pins
VCC_____________________VCC
GND_____________________GND
SCLK_____________________D4
DAT______________________D3
RST______________________D2
Connect LCDI2C 16x2 to Arduino Board
LCDI2C 16x2 pins________________Arduino board pins
VCC___________________________Vin or 5V
GND___________________________GND
SDA____________________________A4
SCL____________________________A5
Libraries for LCDI2C16x02
Sketch for LCDI2C and RTCModule DS1302 (no bridge means A0, A1, A2 not soldered across use LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
and if soldered use LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity ):
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <DS1302.h>
// Init the DS1302
DS1302 rtc(2, 3, 4);
// Init the LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
void setup()
{
// Set the clock to run-mode, and disable the write protection
rtc.halt(false);
rtc.writeProtect(false);
// Setup LCD to 16x2 characters
lcd.begin(16, 2);
// The following lines can be commented out to use the values already stored in the DS1302
rtc.setDOW(FRIDAY); // Set Day-of-Week to FRIDAY
rtc.setTime(12, 54, 0); // Set the time to 12:00:00 (24hr format)
rtc.setDate(7, 2, 2015); // Set the date to August 6th, 2010
}
void loop()
{
// Display time centered on the upper line
lcd.setCursor(4, 0);
lcd.print(rtc.getTimeStr());
// Display abbreviated Day-of-Week in the lower left corner
lcd.setCursor(0, 1);
lcd.print(rtc.getDOWStr(FORMAT_SHORT));
// Display date in the lower right corner
lcd.setCursor(6, 1);
lcd.print(rtc.getDateStr());
// Wait one second before repeating :)
delay (1000);
}