Working Version of the Real Time Clock module DS1307.

Dependents:   Rtc_Ds1307_Sample TAREA_5_PROCESADORES Rtc_Ds1307_lcd_alarma Rtc_Ds1307_Reloj_con_alarma_aplazable ... more

This is my implementation of the DS1307.

I plan to add functionality which will make use of the OSC Input and which will increment the time continuously. A query to the module will then only have to be made when the MBED has been powered down.

Committer:
leihen
Date:
Wed Jun 26 21:05:46 2013 +0000
Revision:
9:5627b407e097
Parent:
8:d0e66fa78e79
Changed initialization

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 5:30531f2121a2 1 #include "mbed.h"
leihen 0:3940f0ad2ca5 2 #include "Rtc_Ds1307.h"
leihen 7:dca20be3ef38 3
leihen 5:30531f2121a2 4 #ifndef DEBUG
leihen 9:5627b407e097 5 //#define DEBUG
leihen 5:30531f2121a2 6 #endif
leihen 3:e89d63f3342e 7 #include "debug.h"
leihen 0:3940f0ad2ca5 8
leihen 1:64274190e842 9 const char *Rtc_Ds1307::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
leihen 0:3940f0ad2ca5 10
leihen 0:3940f0ad2ca5 11
leihen 0:3940f0ad2ca5 12 Rtc_Ds1307::Rtc_Ds1307(PinName sda, PinName scl)
leihen 0:3940f0ad2ca5 13 {
leihen 0:3940f0ad2ca5 14 // Create a new I2C object
leihen 0:3940f0ad2ca5 15 m_rtc = new I2C(sda, scl);
leihen 0:3940f0ad2ca5 16 if (m_rtc == NULL)
leihen 0:3940f0ad2ca5 17 error("Rtc_Ds1307");
leihen 1:64274190e842 18
leihen 1:64274190e842 19 // Set the frequency to standard 100kHz
leihen 1:64274190e842 20 m_rtc->frequency(100000);
leihen 0:3940f0ad2ca5 21 }
leihen 0:3940f0ad2ca5 22
leihen 0:3940f0ad2ca5 23 Rtc_Ds1307::~Rtc_Ds1307()
leihen 0:3940f0ad2ca5 24 {
leihen 0:3940f0ad2ca5 25 if (m_rtc != NULL)
leihen 0:3940f0ad2ca5 26 delete m_rtc;
leihen 0:3940f0ad2ca5 27 }
leihen 0:3940f0ad2ca5 28
leihen 5:30531f2121a2 29 bool Rtc_Ds1307::setTime(Time_rtc& time, bool start, bool thm)
leihen 0:3940f0ad2ca5 30 {
leihen 2:ee81f2c5a706 31 char buffer[7];
leihen 2:ee81f2c5a706 32 INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour, time.min, time.sec);
leihen 2:ee81f2c5a706 33 if (!read(0,buffer,7)) {
leihen 2:ee81f2c5a706 34 ERR("Failed to read from RTC\n");
leihen 2:ee81f2c5a706 35 return false;
leihen 2:ee81f2c5a706 36 }
leihen 2:ee81f2c5a706 37 // Now update only the time part (saving the existing flags)
leihen 2:ee81f2c5a706 38 if (start) { buffer[0] &= 0x7F; } else { buffer[0] |= 0x80; }
leihen 2:ee81f2c5a706 39 buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)& 0x7f);
leihen 2:ee81f2c5a706 40 buffer[1] = decimalToBcd(time.min);
leihen 2:ee81f2c5a706 41 if (thm) {
leihen 2:ee81f2c5a706 42 // AM PM format
leihen 2:ee81f2c5a706 43 buffer[2] = (buffer[2]& 196) | (time.hour>12 ? (0x20 | ((decimalToBcd(time.hour-12)))) : decimalToBcd(time.hour));
leihen 2:ee81f2c5a706 44 }
leihen 2:ee81f2c5a706 45 else {
leihen 2:ee81f2c5a706 46 // 24 hours format
leihen 2:ee81f2c5a706 47 buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour) & 0x3F);
leihen 2:ee81f2c5a706 48 }
leihen 2:ee81f2c5a706 49 buffer[3] = time.wday;
leihen 2:ee81f2c5a706 50 buffer[4] = decimalToBcd(time.date);
leihen 2:ee81f2c5a706 51 buffer[5] = decimalToBcd(time.mon);
leihen 2:ee81f2c5a706 52 buffer[6] = decimalToBcd(time.year-2000);
leihen 2:ee81f2c5a706 53 INFO("Writing new time and date data to RTC\n");
leihen 2:ee81f2c5a706 54 if (!write(0, buffer, 7) ) {
leihen 2:ee81f2c5a706 55 ERR("Failed to write the data to RTC!\n");
leihen 2:ee81f2c5a706 56 return false;
leihen 2:ee81f2c5a706 57 }
leihen 0:3940f0ad2ca5 58 return true;
leihen 0:3940f0ad2ca5 59 }
leihen 0:3940f0ad2ca5 60
leihen 5:30531f2121a2 61 bool Rtc_Ds1307::getTime(Time_rtc& time)
leihen 0:3940f0ad2ca5 62 {
leihen 1:64274190e842 63 char buffer[7];
leihen 1:64274190e842 64 bool thm = false;
leihen 1:64274190e842 65
leihen 1:64274190e842 66 INFO("Getting time from RTC\n");
leihen 2:ee81f2c5a706 67 if (!read(0, buffer, 7) ) {
leihen 1:64274190e842 68 // Failed to read
leihen 1:64274190e842 69 ERR("Failed to read from RTC\n");
leihen 1:64274190e842 70 return false;
leihen 1:64274190e842 71 }
leihen 1:64274190e842 72 thm = ((buffer[2] & 64) == 64);
leihen 1:64274190e842 73 time.sec = bcdToDecimal(buffer[0]&0x7F);
leihen 1:64274190e842 74 time.min = bcdToDecimal(buffer[1]);
leihen 1:64274190e842 75 if (thm) {
leihen 1:64274190e842 76 // in 12-hour-mode, we need to add 12 hours if PM bit is set
leihen 1:64274190e842 77 time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 31 );
leihen 1:64274190e842 78 if ((buffer[2] & 32) == 32)
leihen 1:64274190e842 79 time.hour += 12;
leihen 1:64274190e842 80 }
leihen 1:64274190e842 81 else {
leihen 1:64274190e842 82 time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 63 );
leihen 1:64274190e842 83 }
leihen 1:64274190e842 84 time.wday = buffer[3];
leihen 1:64274190e842 85 time.date = Rtc_Ds1307::bcdToDecimal( buffer[4]);
leihen 1:64274190e842 86 time.mon = Rtc_Ds1307::bcdToDecimal( buffer[5]);
leihen 2:ee81f2c5a706 87 time.year = Rtc_Ds1307::bcdToDecimal(buffer[6]) + 2000; // plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900
leihen 2:ee81f2c5a706 88
leihen 2:ee81f2c5a706 89 return true;
leihen 2:ee81f2c5a706 90 }
leihen 2:ee81f2c5a706 91
leihen 2:ee81f2c5a706 92
leihen 2:ee81f2c5a706 93 bool Rtc_Ds1307::startClock()
leihen 2:ee81f2c5a706 94 {
leihen 2:ee81f2c5a706 95 char strtStop;
leihen 2:ee81f2c5a706 96
leihen 2:ee81f2c5a706 97 INFO ("Reading clock start/stop register value\n");
leihen 2:ee81f2c5a706 98 if (!read(0, &strtStop, 1)) {
leihen 2:ee81f2c5a706 99 ERR("Failed to read clock start stop register !\n");
leihen 2:ee81f2c5a706 100 return false;
leihen 2:ee81f2c5a706 101 }
leihen 2:ee81f2c5a706 102
leihen 2:ee81f2c5a706 103 strtStop &= 0x7F;
leihen 2:ee81f2c5a706 104
leihen 2:ee81f2c5a706 105 INFO("Writing back start/stop register value\n");
leihen 2:ee81f2c5a706 106 if (!write(0, &strtStop, 1)) {
leihen 2:ee81f2c5a706 107 ERR("Failed to write the start stop register !\n");
leihen 2:ee81f2c5a706 108 return false;
leihen 2:ee81f2c5a706 109 }
leihen 2:ee81f2c5a706 110
leihen 2:ee81f2c5a706 111 INFO("Start/stop register value successfully written\n");
leihen 2:ee81f2c5a706 112 return true;
leihen 2:ee81f2c5a706 113 }
leihen 2:ee81f2c5a706 114
leihen 2:ee81f2c5a706 115 bool Rtc_Ds1307::stopClock()
leihen 2:ee81f2c5a706 116 {
leihen 2:ee81f2c5a706 117 char strtStop;
leihen 2:ee81f2c5a706 118
leihen 2:ee81f2c5a706 119 INFO ("Reading clock start/stop register value\n");
leihen 2:ee81f2c5a706 120 if (!read(0, &strtStop, 1)) {
leihen 2:ee81f2c5a706 121 ERR("Failed to read clock start stop register !\n");
leihen 2:ee81f2c5a706 122 return false;
leihen 2:ee81f2c5a706 123 }
leihen 1:64274190e842 124
leihen 2:ee81f2c5a706 125 strtStop |= 0x80;
leihen 2:ee81f2c5a706 126
leihen 2:ee81f2c5a706 127 INFO("Writing back start/stop register value\n");
leihen 2:ee81f2c5a706 128 if (!write(0, &strtStop, 1)) {
leihen 2:ee81f2c5a706 129 ERR("Failed to write the start stop register !\n");
leihen 2:ee81f2c5a706 130 return false;
leihen 2:ee81f2c5a706 131 }
leihen 2:ee81f2c5a706 132
leihen 2:ee81f2c5a706 133 INFO("Start/stop register value successfully written\n");
leihen 2:ee81f2c5a706 134 return true;
leihen 0:3940f0ad2ca5 135 }
leihen 1:64274190e842 136
leihen 5:30531f2121a2 137 bool Rtc_Ds1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs)
leihen 2:ee81f2c5a706 138 {
leihen 2:ee81f2c5a706 139 char reg;
leihen 2:ee81f2c5a706 140 INFO("Reading register value first\n");
leihen 2:ee81f2c5a706 141
leihen 2:ee81f2c5a706 142 if (!read(7,&reg, 1)) {
leihen 2:ee81f2c5a706 143 ERR("Failed to read register value !\n");
leihen 2:ee81f2c5a706 144 return false;
leihen 2:ee81f2c5a706 145 }
leihen 2:ee81f2c5a706 146 INFO("[Reg:0x07] = %02x\n", reg);
leihen 2:ee81f2c5a706 147
leihen 2:ee81f2c5a706 148 // preserve the OUT control bit while writing the frequency and enable bits
leihen 2:ee81f2c5a706 149 reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03);
leihen 2:ee81f2c5a706 150
leihen 2:ee81f2c5a706 151 INFO("Writing back register value\n");
leihen 2:ee81f2c5a706 152 INFO("[Reg:0x07] = %02x\n", reg);
leihen 2:ee81f2c5a706 153
leihen 2:ee81f2c5a706 154 if (!write(7, &reg, 1)) {
leihen 2:ee81f2c5a706 155 ERR("Failed to write register value !\n");
leihen 2:ee81f2c5a706 156 return false;
leihen 2:ee81f2c5a706 157 }
leihen 2:ee81f2c5a706 158
leihen 2:ee81f2c5a706 159 INFO("Successfully changed the square wave output.\n");
leihen 2:ee81f2c5a706 160 return true;
leihen 2:ee81f2c5a706 161 }
leihen 2:ee81f2c5a706 162
leihen 2:ee81f2c5a706 163
leihen 1:64274190e842 164
leihen 1:64274190e842 165 bool Rtc_Ds1307::read(int address, char *buffer, int len)
leihen 1:64274190e842 166 {
leihen 1:64274190e842 167 char buffer2[2] = {(char)address, 0};
leihen 1:64274190e842 168
leihen 2:ee81f2c5a706 169 // m_rtc->start();
leihen 1:64274190e842 170 if (m_rtc->write(0xd0, buffer2, 1) != 0) {
leihen 1:64274190e842 171 ERR("Failed to write register address on rtv!\n");
leihen 1:64274190e842 172 m_rtc->stop();
leihen 1:64274190e842 173 return false;
leihen 1:64274190e842 174 }
leihen 1:64274190e842 175 if (m_rtc->read(0xd0, buffer, len) != 0) {
leihen 1:64274190e842 176 ERR("Failed to read register !\n");
leihen 1:64274190e842 177 return false;
leihen 1:64274190e842 178 }
leihen 1:64274190e842 179 m_rtc->stop();
leihen 1:64274190e842 180
leihen 1:64274190e842 181 INFO("Successfully read %d registers from RTC\n", len);
leihen 1:64274190e842 182 return true;
leihen 1:64274190e842 183 }
leihen 1:64274190e842 184
leihen 1:64274190e842 185 bool Rtc_Ds1307::write(int address, char *buffer, int len)
leihen 1:64274190e842 186 {
leihen 1:64274190e842 187 char buffer2[10];
leihen 1:64274190e842 188 buffer2[0] = address&0xFF;
leihen 1:64274190e842 189 for (int i = 0 ; i < len ; i++)
leihen 1:64274190e842 190 buffer2[i+1] = buffer[i];
leihen 1:64274190e842 191
leihen 2:ee81f2c5a706 192 // m_rtc->start();
leihen 1:64274190e842 193 if (m_rtc->write(0xd0, buffer2, len+1) != 0) {
leihen 1:64274190e842 194 ERR("Failed to write data to rtc\n");
leihen 1:64274190e842 195 m_rtc->stop();
leihen 1:64274190e842 196 return false;
leihen 1:64274190e842 197 }
leihen 1:64274190e842 198 m_rtc->stop();
leihen 1:64274190e842 199 return true;
leihen 7:dca20be3ef38 200 }
leihen 7:dca20be3ef38 201
leihen 7:dca20be3ef38 202
leihen 7:dca20be3ef38 203
leihen 7:dca20be3ef38 204
leihen 7:dca20be3ef38 205 RtcCls::RtcCls(PinName sda, PinName scl, PinName sqw, bool bUseSqw)
leihen 7:dca20be3ef38 206 : Rtc_Ds1307(sda, scl), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL)
leihen 7:dca20be3ef38 207 {
leihen 9:5627b407e097 208 Time_rtc t;
leihen 9:5627b407e097 209 // query time from device
leihen 9:5627b407e097 210 getTime(t);
leihen 9:5627b407e097 211 // sync the time with MBED RTC
leihen 9:5627b407e097 212 struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
leihen 9:5627b407e097 213 m_time = mktime(&now);
leihen 9:5627b407e097 214 set_time(m_time);
leihen 9:5627b407e097 215
leihen 7:dca20be3ef38 216 // Only register the callback and start the SQW if requested to do so. Otherwise the system
leihen 7:dca20be3ef38 217 // will use the MBED built-in RTC.
leihen 7:dca20be3ef38 218 if (m_bUseSqw) {
leihen 7:dca20be3ef38 219 // start the wave
leihen 7:dca20be3ef38 220 setSquareWaveOutput(true, RS1Hz);
leihen 7:dca20be3ef38 221 // register callback from now on the time will be maintained by the square wave input
leihen 7:dca20be3ef38 222 m_sqw.rise(this, &RtcCls::_callback);
leihen 7:dca20be3ef38 223 }
leihen 7:dca20be3ef38 224 }
leihen 7:dca20be3ef38 225
leihen 7:dca20be3ef38 226 void RtcCls::_callback(void)
leihen 7:dca20be3ef38 227 {
leihen 8:d0e66fa78e79 228 // INFO("Tick!");
leihen 7:dca20be3ef38 229 // Simply increase the number of seconds
leihen 7:dca20be3ef38 230 m_time++;
leihen 8:d0e66fa78e79 231 // if (m_bAlarmEnabled && (m_time == m_alarmTime)) {
leihen 8:d0e66fa78e79 232 // if (m_alarmfunc != NULL)
leihen 8:d0e66fa78e79 233 // m_alarmfunc();
leihen 8:d0e66fa78e79 234 // m_bAlarmEnabled = false;
leihen 8:d0e66fa78e79 235 // }
leihen 7:dca20be3ef38 236 }
leihen 7:dca20be3ef38 237
leihen 7:dca20be3ef38 238 time_t RtcCls::getTime()
leihen 7:dca20be3ef38 239 {
leihen 7:dca20be3ef38 240 // when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value
leihen 7:dca20be3ef38 241 if (!m_bUseSqw) {
leihen 7:dca20be3ef38 242 Time_rtc t;
leihen 7:dca20be3ef38 243 getTime(t);
leihen 8:d0e66fa78e79 244 struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
leihen 7:dca20be3ef38 245 m_time = mktime(&now);
leihen 8:d0e66fa78e79 246 INFO("getting time %02d.%02d.%04d %02d:%02d:%02d Ticks=%08lx", t.date, t.mon, t.year, t.hour, t.min, t.sec, m_time);
leihen 8:d0e66fa78e79 247 }
leihen 8:d0e66fa78e79 248 else {
leihen 8:d0e66fa78e79 249 INFO("getting time Ticks=%08lx", m_time);
leihen 7:dca20be3ef38 250 }
leihen 7:dca20be3ef38 251 return m_time;
leihen 7:dca20be3ef38 252 }
leihen 7:dca20be3ef38 253
leihen 7:dca20be3ef38 254 void RtcCls::setTime(time_t t)
leihen 7:dca20be3ef38 255 {
leihen 7:dca20be3ef38 256 Time_rtc tim;
leihen 7:dca20be3ef38 257 struct tm *now;
leihen 7:dca20be3ef38 258 now = localtime(&t);
leihen 7:dca20be3ef38 259
leihen 7:dca20be3ef38 260 tim.sec = now->tm_sec;
leihen 7:dca20be3ef38 261 tim.min = now->tm_min;
leihen 7:dca20be3ef38 262 tim.hour = now->tm_hour;
leihen 7:dca20be3ef38 263 tim.date = now->tm_mday;
leihen 8:d0e66fa78e79 264 tim.mon = now->tm_mon+1;
leihen 7:dca20be3ef38 265 tim.year = now->tm_year + 1900;
leihen 7:dca20be3ef38 266 tim.wday = now->tm_wday +1;
leihen 7:dca20be3ef38 267
leihen 7:dca20be3ef38 268 setTime( tim, true, true);
leihen 8:d0e66fa78e79 269 set_time(t);
leihen 7:dca20be3ef38 270 }