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
Rtc_Ds1307.cpp
00001 #include "mbed.h" 00002 #include "Rtc_Ds1307.h" 00003 00004 #ifndef DEBUG 00005 //#define DEBUG 00006 #endif 00007 #include "debug.h" 00008 00009 const char *Rtc_Ds1307::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }; 00010 00011 00012 Rtc_Ds1307::Rtc_Ds1307(PinName sda, PinName scl) 00013 { 00014 // Create a new I2C object 00015 m_rtc = new I2C(sda, scl); 00016 if (m_rtc == NULL) 00017 error("Rtc_Ds1307"); 00018 00019 // Set the frequency to standard 100kHz 00020 m_rtc->frequency(100000); 00021 } 00022 00023 Rtc_Ds1307::~Rtc_Ds1307() 00024 { 00025 if (m_rtc != NULL) 00026 delete m_rtc; 00027 } 00028 00029 bool Rtc_Ds1307::setTime(Time_rtc& time, bool start, bool thm) 00030 { 00031 char buffer[7]; 00032 INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour , time.min , time.sec ); 00033 if (!read(0,buffer,7)) { 00034 ERR("Failed to read from RTC\n"); 00035 return false; 00036 } 00037 // Now update only the time part (saving the existing flags) 00038 if (start) { buffer[0] &= 0x7F; } else { buffer[0] |= 0x80; } 00039 buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec )& 0x7f); 00040 buffer[1] = decimalToBcd(time.min ); 00041 if (thm) { 00042 // AM PM format 00043 buffer[2] = (buffer[2]& 196) | (time.hour >12 ? (0x20 | ((decimalToBcd(time.hour -12)))) : decimalToBcd(time.hour )); 00044 } 00045 else { 00046 // 24 hours format 00047 buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour ) & 0x3F); 00048 } 00049 buffer[3] = time.wday ; 00050 buffer[4] = decimalToBcd(time.date ); 00051 buffer[5] = decimalToBcd(time.mon ); 00052 buffer[6] = decimalToBcd(time.year -2000); 00053 INFO("Writing new time and date data to RTC\n"); 00054 if (!write(0, buffer, 7) ) { 00055 ERR("Failed to write the data to RTC!\n"); 00056 return false; 00057 } 00058 return true; 00059 } 00060 00061 bool Rtc_Ds1307::getTime(Time_rtc& time) 00062 { 00063 char buffer[7]; 00064 bool thm = false; 00065 00066 INFO("Getting time from RTC\n"); 00067 if (!read(0, buffer, 7) ) { 00068 // Failed to read 00069 ERR("Failed to read from RTC\n"); 00070 return false; 00071 } 00072 thm = ((buffer[2] & 64) == 64); 00073 time.sec = bcdToDecimal(buffer[0]&0x7F); 00074 time.min = bcdToDecimal(buffer[1]); 00075 if (thm) { 00076 // in 12-hour-mode, we need to add 12 hours if PM bit is set 00077 time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 31 ); 00078 if ((buffer[2] & 32) == 32) 00079 time.hour += 12; 00080 } 00081 else { 00082 time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 63 ); 00083 } 00084 time.wday = buffer[3]; 00085 time.date = Rtc_Ds1307::bcdToDecimal( buffer[4]); 00086 time.mon = Rtc_Ds1307::bcdToDecimal( buffer[5]); 00087 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 00088 00089 return true; 00090 } 00091 00092 00093 bool Rtc_Ds1307::startClock() 00094 { 00095 char strtStop; 00096 00097 INFO ("Reading clock start/stop register value\n"); 00098 if (!read(0, &strtStop, 1)) { 00099 ERR("Failed to read clock start stop register !\n"); 00100 return false; 00101 } 00102 00103 strtStop &= 0x7F; 00104 00105 INFO("Writing back start/stop register value\n"); 00106 if (!write(0, &strtStop, 1)) { 00107 ERR("Failed to write the start stop register !\n"); 00108 return false; 00109 } 00110 00111 INFO("Start/stop register value successfully written\n"); 00112 return true; 00113 } 00114 00115 bool Rtc_Ds1307::stopClock() 00116 { 00117 char strtStop; 00118 00119 INFO ("Reading clock start/stop register value\n"); 00120 if (!read(0, &strtStop, 1)) { 00121 ERR("Failed to read clock start stop register !\n"); 00122 return false; 00123 } 00124 00125 strtStop |= 0x80; 00126 00127 INFO("Writing back start/stop register value\n"); 00128 if (!write(0, &strtStop, 1)) { 00129 ERR("Failed to write the start stop register !\n"); 00130 return false; 00131 } 00132 00133 INFO("Start/stop register value successfully written\n"); 00134 return true; 00135 } 00136 00137 bool Rtc_Ds1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs) 00138 { 00139 char reg; 00140 INFO("Reading register value first\n"); 00141 00142 if (!read(7,®, 1)) { 00143 ERR("Failed to read register value !\n"); 00144 return false; 00145 } 00146 INFO("[Reg:0x07] = %02x\n", reg); 00147 00148 // preserve the OUT control bit while writing the frequency and enable bits 00149 reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03); 00150 00151 INFO("Writing back register value\n"); 00152 INFO("[Reg:0x07] = %02x\n", reg); 00153 00154 if (!write(7, ®, 1)) { 00155 ERR("Failed to write register value !\n"); 00156 return false; 00157 } 00158 00159 INFO("Successfully changed the square wave output.\n"); 00160 return true; 00161 } 00162 00163 00164 00165 bool Rtc_Ds1307::read(int address, char *buffer, int len) 00166 { 00167 char buffer2[2] = {(char)address, 0}; 00168 00169 // m_rtc->start(); 00170 if (m_rtc->write(0xd0, buffer2, 1) != 0) { 00171 ERR("Failed to write register address on rtv!\n"); 00172 m_rtc->stop(); 00173 return false; 00174 } 00175 if (m_rtc->read(0xd0, buffer, len) != 0) { 00176 ERR("Failed to read register !\n"); 00177 return false; 00178 } 00179 m_rtc->stop(); 00180 00181 INFO("Successfully read %d registers from RTC\n", len); 00182 return true; 00183 } 00184 00185 bool Rtc_Ds1307::write(int address, char *buffer, int len) 00186 { 00187 char buffer2[10]; 00188 buffer2[0] = address&0xFF; 00189 for (int i = 0 ; i < len ; i++) 00190 buffer2[i+1] = buffer[i]; 00191 00192 // m_rtc->start(); 00193 if (m_rtc->write(0xd0, buffer2, len+1) != 0) { 00194 ERR("Failed to write data to rtc\n"); 00195 m_rtc->stop(); 00196 return false; 00197 } 00198 m_rtc->stop(); 00199 return true; 00200 } 00201 00202 00203 00204 00205 RtcCls::RtcCls(PinName sda, PinName scl, PinName sqw, bool bUseSqw) 00206 : Rtc_Ds1307(sda, scl), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL) 00207 { 00208 Time_rtc t; 00209 // query time from device 00210 getTime(t); 00211 // sync the time with MBED RTC 00212 struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; 00213 m_time = mktime(&now); 00214 set_time(m_time); 00215 00216 // Only register the callback and start the SQW if requested to do so. Otherwise the system 00217 // will use the MBED built-in RTC. 00218 if (m_bUseSqw) { 00219 // start the wave 00220 setSquareWaveOutput(true, RS1Hz); 00221 // register callback from now on the time will be maintained by the square wave input 00222 m_sqw.rise(this, &RtcCls::_callback); 00223 } 00224 } 00225 00226 void RtcCls::_callback(void) 00227 { 00228 // INFO("Tick!"); 00229 // Simply increase the number of seconds 00230 m_time++; 00231 // if (m_bAlarmEnabled && (m_time == m_alarmTime)) { 00232 // if (m_alarmfunc != NULL) 00233 // m_alarmfunc(); 00234 // m_bAlarmEnabled = false; 00235 // } 00236 } 00237 00238 time_t RtcCls::getTime() 00239 { 00240 // when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value 00241 if (!m_bUseSqw) { 00242 Time_rtc t; 00243 getTime(t); 00244 struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; 00245 m_time = mktime(&now); 00246 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); 00247 } 00248 else { 00249 INFO("getting time Ticks=%08lx", m_time); 00250 } 00251 return m_time; 00252 } 00253 00254 void RtcCls::setTime(time_t t) 00255 { 00256 Time_rtc tim; 00257 struct tm *now; 00258 now = localtime(&t); 00259 00260 tim.sec = now->tm_sec; 00261 tim.min = now->tm_min; 00262 tim.hour = now->tm_hour; 00263 tim.date = now->tm_mday; 00264 tim.mon = now->tm_mon+1; 00265 tim.year = now->tm_year + 1900; 00266 tim.wday = now->tm_wday +1; 00267 00268 setTime( tim, true, true); 00269 set_time(t); 00270 }
Generated on Thu Jul 14 2022 15:34:48 by 1.7.2