Hello,
I need some beginner help again. I have put together a digital clock using the DS1302 and a 20x4 LCD. Its all fine except the Date part. The format shows MM/DD/YYYY and I want DD/MM/YYYY. I can't work out how to change this. Can you give me some pointers?
Here is my code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include<DS1302.h>
DS1302 rtc(6,7,8);
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
void setup(){
rtc.halt(false);
rtc.writeProtect(false);
// rtc.setDOW(WEDNESDAY); // Comment this
// rtc.setTime(21,54,00); // out after
// rtc.setDate(11,3,2021); // time set.
Serial.begin(9600);
lcd.init();
lcd.backlight();
}
void loop(){
lcd.setCursor(2,0);
lcd.print("**Mark's Clock**");
lcd.setCursor(0,1);
lcd.print("Time: ");
lcd.print(rtc.getTimeStr());
lcd.setCursor(0,2);
lcd.print("Day: ");
lcd.print(rtc.getDOWStr());
lcd.setCursor(0,3);
lcd.print("Date: ");
lcd.print(rtc.getDateStr());
Serial.println(rtc.getTimeStr());
Serial.println(rtc.getDateStr());
Serial.println(rtc.getDOWStr());
delay(1000);
}
Here is the library I am using.
CCP
/*
DS1302.cpp - Arduino library support for the DS1302 Trickle Charge Timekeeping Chip
Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
This library has been made to easily interface and use the DS1302 RTC with
the Arduino.
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 "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[4]);
t.mon = _decode(_burstArray[3]);
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;
}
.h
/*
DS1302.h - Arduino library support for the DS1302 Trickle Charge Timekeeping Chip
Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
This library has been made to easily interface and use the DS1302 RTC with
the Arduino.
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.
*/
#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