DS3232M RTC demo program. Tested on the K64F (this example) and the KL25Z, but should work on any platform by changing the SDA and SCL pins. USB serial baud rate is 230400, tested on TeraTerm. Demo includes setting the DS3232's time, turning on and off the 32KHz and 1Hz outputs and accessing the DS3232's temperature. Also included are DS3232 user RAM access tests and user RAM CRC data calculations. Since user RAM is battery backed up, CRC routines are included to insure that the data stored in user RAM is intact.
Dependencies: ds3232m mbed mbed-rtos
main.cpp
00001 #include "mbed.h" 00002 #include "rtos.h" //mbed rtos - uncomment to make RTOS available 00003 #include "ds3232m.h" //Maxim RTC 00004 00005 #ifdef RTOS_H 00006 Mutex MutexI2cWait_1; //lock/unlock I2C requests 00007 RawSerial pc(USBTX, USBRX); //console interface for RTOS 00008 #else 00009 Serial pc(USBTX, USBRX); //console interface 00010 #endif //RTOS_H 00011 00012 #define SDA0 D14 //assuming arduino pins 00013 #define SCL0 D15 00014 ds3232m rtc(SDA0, SCL0, 400000); //Maxim real time clock 00015 00016 //--------------------------------------------------------------------------------------------------------------------------------------// 00017 // Time variables 00018 00019 time_t ctTime; //time structure 00020 int DST = 1; //Daylight Saving Time (or as defined in .ini file) 00021 int TZone = -8; //Time Zone from UTC (or as defined in .ini file) 00022 char timebuf_hms[10]; //local time format buffer - 21:16:43 00023 char timebuf_dMyy[14]; //local time format buffer - 01-Apr-2014 00024 char timebuf_dow[1]; //local time format buffer - 5 00025 int StartTime = 0; //time we powered up 00026 bool allowDisplayTime = false; //used to stop displaying date/time when entering data from the console 00027 00028 //--------------------------------------------------------------------------------------------------------------------------------------// 00029 //Variables for USB Serial Port RX 00030 00031 uint32_t pcRxQty = 0; //RX data counter/pointer 00032 char pcRxBuffer[128]; //RX data buffer 00033 bool pcRxLine = false; //CR or LF detected (end of line) 00034 bool pcRxEOB = false; //RX buffer is full!!! cannot accept any more characters 00035 char inchar = 0; //RX input character 00036 00037 //--------------------------------------------------------------------------------------------------------------------------------------// 00038 // various Mutex lock/unlock definitions 00039 00040 void lockI2C() { 00041 #ifdef RTOS_H 00042 MutexI2cWait_1.lock(); 00043 #endif //RTOS_H 00044 } 00045 00046 void unlockI2C() { 00047 #ifdef RTOS_H 00048 MutexI2cWait_1.unlock(); 00049 #endif //RTOS_H 00050 } 00051 00052 //--------------------------------------------------------------------------------------------------------------------------------------// 00053 // This function is called when a character goes into the RX buffer. 00054 00055 #define DOUPONELINE "\033[1A" 00056 #define BS 0x08 //ascii backspace 00057 #define CR 0x0d //ascii CR 00058 #define LF 0x0a //ascii LF 00059 #define ticC 0x03 //ascii control C 00060 #define DEGC_DEGF_FLOAT 9.0 / 5.0 + 32.0 00061 00062 void PcRxChar(char inchar) { 00063 if(inchar == CR) pc.printf(" %c %c", BS, BS); //NOTE: Bug in K64F has issue with CR and/or LF, these 2 lines are needed 00064 if(inchar == LF) pc.printf(" %c %c", BS, BS); 00065 if(inchar == BS) { 00066 if(pcRxQty == 0) { 00067 pcRxBuffer[pcRxQty] = 0; 00068 } else { 00069 pc.printf("%c %c", BS, BS); 00070 pcRxQty--; 00071 pcRxBuffer[pcRxQty] = 0; 00072 } 00073 } else if((inchar == CR) || (inchar == LF)) { 00074 pcRxLine = true; 00075 pc.printf("\r\n"); 00076 } else if(inchar == ticC) { 00077 NVIC_SystemReset(); 00078 } else { 00079 if(pcRxQty < (sizeof(pcRxBuffer) - 2)) { 00080 pcRxBuffer[pcRxQty] = inchar; 00081 pcRxQty++; 00082 pcRxBuffer[pcRxQty] = 0; 00083 pc.printf("%c", pcRxBuffer[pcRxQty - 1]); 00084 } else { 00085 pc.printf ("\r\n*** pcRxBuffer is full!!\r\n"); 00086 pcRxEOB = true; 00087 } 00088 } 00089 } 00090 00091 //--------------------------------------------------------------------------------------------------------------------------------------// 00092 // Read received chars from USB UART interrupt 00093 00094 void PcRxIRQ(void){ 00095 /* 00096 #if defined(TARGET_KL25Z) 00097 NVIC_DisableIRQ(UART0_IRQn); // n=0, 1 or 2 Disable Rx interrupt on kl25z 00098 #endif 00099 #if defined(TARGET_K64F) 00100 NVIC_DisableIRQ(UART0_RX_TX_IRQn); // n=0, 1 or 2 Disable Rx interrupt on k64f 00101 #endif 00102 #if defined(TARGET_LPC1768) 00103 LPC_UART0->IER = 0; //Disable Rx interrupt on mbed1768 00104 #endif 00105 */ 00106 while (pc.readable()) { 00107 inchar = pc.getc(); //read data from USB 00108 PcRxChar(inchar); //go process char 00109 } 00110 /* 00111 #if defined(TARGET_KL25Z) 00112 NVIC_EnableIRQ(UART0_IRQn); // n=0, 1 or 2 Re-enable Rx interrupt on kl25z 00113 #endif 00114 #if defined(TARGET_K64F) 00115 NVIC_EnableIRQ(UART0_RX_TX_IRQn); // n=0, 1 or 2 Re-enable Rx interrupt on k64f 00116 #endif 00117 #if defined(TARGET_LPC1768) 00118 LPC_UART0->IER = 1; //RE-enable Rx interrupt on mbed1768 00119 #endif 00120 */ 00121 } 00122 00123 //--------------------------------------------------------------------------------------------------------------------------------------// 00124 //clear RxData buffer with all 00's and clear flags 00125 00126 void pcClrLineBuf() { 00127 pcRxQty = 0; // data counter/pointer 00128 for(int i = 0; i < (sizeof(pcRxBuffer) - 1); i++) pcRxBuffer[i] = 0; // clear out rx buffer 00129 pcRxLine = false; 00130 pcRxEOB = false; 00131 } 00132 00133 //--------------------------------------------------------------------------------------------------------------------------------------// 00134 // Update time display values 00135 00136 void UpdateTimeRegs() { 00137 strftime(timebuf_dMyy, 14, "%d-%b-%Y", localtime(&ctTime)); 00138 strftime(timebuf_hms, 10, "%H:%M:%S", localtime(&ctTime)); 00139 strftime(timebuf_dow, 1, "%u", localtime(&ctTime)); 00140 } 00141 00142 void UpdateTime() { 00143 ctTime = time(NULL) + ((TZone + DST) * 3600); //timezone and dst offsets 00144 UpdateTimeRegs(); 00145 } 00146 00147 //--------------------------------------------------------------------------------------------------------------------------------------// 00148 // display current local date and time 00149 00150 void PrintDateTime() { 00151 pc.printf("%sDate: %s ", DOUPONELINE, timebuf_dMyy); 00152 pc.printf("Time: %s \r\n", timebuf_hms); 00153 } 00154 00155 //--------------------------------------------------------------------------------------------------------------------------------------// 00156 //Manually set the date and time 00157 00158 ds3232m::Time_rtc rtc_m = {}; 00159 struct tm t; 00160 00161 bool SetRTC() { 00162 pc.printf("Enter current date and time:\n"); 00163 pc.printf("MM DD YY HH MM SS[enter]\n"); 00164 pcClrLineBuf(); 00165 00166 //wait for string above 00167 do{ 00168 #ifdef RTOS_H 00169 Thread::wait(10); 00170 #else 00171 wait_ms(10); 00172 #endif 00173 } while((pcRxLine == false) && (pcRxEOB == false)); 00174 00175 //load up the time structure 00176 t.tm_year = (2000 + ((pcRxBuffer[6] - '0') * 10) + pcRxBuffer[7] - '0'); 00177 t.tm_mon = (((pcRxBuffer[0] - '0') * 10) + pcRxBuffer[1] - '0'); 00178 t.tm_mday = (((pcRxBuffer[3] - '0') * 10) + pcRxBuffer[4] - '0'); 00179 t.tm_hour = (((pcRxBuffer[9] - '0') * 10) + pcRxBuffer[10] - '0'); 00180 t.tm_min = (((pcRxBuffer[12] - '0') * 10) + pcRxBuffer[13] - '0'); 00181 t.tm_sec = (((pcRxBuffer[15] - '0') * 10) + pcRxBuffer[16] - '0'); 00182 00183 //adjust for tm structure required values 00184 t.tm_year = t.tm_year - 1900; 00185 t.tm_mon = t.tm_mon - 1; 00186 t.tm_wday = t.tm_wday & 7; 00187 00188 //if error exists, exit without changing time 00189 if(t.tm_year < 113) return(32); 00190 if(t.tm_mon > 12) return(16); 00191 if(t.tm_mday > 31) return(8); 00192 if(t.tm_hour > 23) return(4); 00193 if(t.tm_min > 59) return(2); 00194 if(t.tm_sec > 59) return(1); 00195 00196 //set up the DS3232's RTC 00197 rtc_m.sec = t.tm_sec; 00198 rtc_m.min = t.tm_min; 00199 rtc_m.hour = t.tm_hour; 00200 rtc_m.wday = t.tm_wday; 00201 rtc_m.date = t.tm_mday; 00202 rtc_m.mon = t.tm_mon + 1; 00203 rtc_m.year = t.tm_year + 1900; 00204 rtc.setTime(rtc_m); //(time structure) 00205 00206 //set the mbed's time 00207 time_t ctTime = mktime(&t); 00208 //reset system up time since it will be out of whack once the time is updated 00209 StartTime = ctTime; //have to change sysuptime now 00210 ctTime = ctTime - (TZone + DST) * 3600; //take out local time 00211 set_time(ctTime); 00212 UpdateTime(); 00213 return(0); 00214 } 00215 00216 //--------------------------------------------------------------------------------------------------------------------------------------// 00217 // Load the local mbed-RTC from that external DS3232 RTC 00218 00219 void loadRTC() { 00220 lockI2C(); 00221 //get data from DS3232 00222 rtc.getTime(rtc_m); 00223 unlockI2C(); 00224 t.tm_sec = rtc_m.sec; 00225 t.tm_min = rtc_m.min; 00226 t.tm_hour = rtc_m.hour; 00227 t.tm_mday = rtc_m.date; 00228 t.tm_mon = rtc_m.mon - 1; 00229 t.tm_year = rtc_m.year - 1900; 00230 00231 //set the mbed's time 00232 time_t ctTime = mktime(&t); 00233 ctTime = ctTime - (TZone + DST) * 3600; //take out local time 00234 set_time(ctTime); 00235 UpdateTime(); 00236 } 00237 00238 //--------------------------------------------------------------------------------------------------------------------------------------// 00239 // Pull the temperature out of the DS3232 RTC 00240 00241 void Get3232Temp() { 00242 pc.printf("%c", BS); 00243 lockI2C(); 00244 if(rtc.startTempCycle(rtc_m) == true) { 00245 unlockI2C(); 00246 pc.printf(" - DS3232M start converstion ok \r\n"); 00247 } else { 00248 unlockI2C(); 00249 pc.printf(" - DS3232M start converstion BUSY!!! \r\n"); 00250 } 00251 //wait for DS3232 temperature conversion to finish 00252 int i = 80; 00253 for(i = 80; i > 0; i--) { 00254 #ifdef RTOS_H 00255 Thread::wait(20); 00256 #else 00257 wait_ms(20); 00258 #endif 00259 lockI2C(); 00260 if((rtc.checkTempBusy(rtc_m)) == true) break; 00261 unlockI2C(); 00262 } 00263 00264 //timed out or display temperature 00265 if(i > 0) { 00266 float ds3232tempC = rtc.getTemperature(rtc_m); 00267 unlockI2C(); 00268 #if (defined(TARGET_K64F) || defined(TARGET_DISCO_F746NG)) 00269 pc.printf(" - DS3232M Temperature: %.2fC %.1fF\r\n", (double)ds3232tempC, (double)ds3232tempC * DEGC_DEGF_FLOAT); 00270 #else 00271 pc.printf(" - DS3232M Temperature: %.2fC %.1fF\r\n", ds3232tempC, ds3232tempC * DEGC_DEGF_FLOAT); 00272 #endif 00273 } else { 00274 unlockI2C(); 00275 pc.printf("*** DS3232M Temperature timeout!!!!\r\n"); 00276 } 00277 } 00278 00279 //--------------------------------------------------------------------------------------------------------------------------------------// 00280 // Checking for characters to execute commands from. It's a thread if RTOS is used. 00281 00282 #ifdef RTOS_H 00283 void cli_thread(void const *argument) { 00284 pc.printf(" - Starting CLI RTOS thread\r\n"); 00285 while (true) { //while loop only for RTOS 00286 Thread::wait(73); 00287 #else 00288 void cli_thread() { 00289 #endif 00290 if(pcRxQty != 0) { 00291 pc.printf("\r\n"); 00292 if(pcRxBuffer[0] == 'A') rtc.set32KhzOutput(rtc_m, true, false); //turn on 32KHz output 00293 if(pcRxBuffer[0] == 'a') rtc.set32KhzOutput(rtc_m, false, false); //turn off 32KHz output 00294 if(pcRxBuffer[0] == 'B') rtc.set1hzOutput(rtc_m, true, false); //turn on 1Hz output 00295 if(pcRxBuffer[0] == 'b') rtc.set1hzOutput(rtc_m,false, false); //turn off 1Hz output 00296 if(pcRxBuffer[0] == 'c') { 00297 allowDisplayTime = true; 00298 SetRTC(); //change DS3232 time 00299 allowDisplayTime = false; 00300 pcRxBuffer[0] = 'c'; 00301 } 00302 uint8_t errorValue = 0; 00303 if(pcRxBuffer[0] == 'g') { //get and display stored data string 00304 errorValue = rtc.getUserRAM(pcRxBuffer, rtc_m, 128, 124); 00305 if(errorValue) { 00306 pc.printf("'Get' user RAM error: %d\r\n", errorValue); 00307 } else if(pcRxBuffer[0] == NULL) { 00308 pc.printf("User RAM empty!!\r\n"); 00309 } else { 00310 //pcRxBuffer[31] = NULL; //guarantee that the string max length is 32 bytes 00311 pc.printf("%s\r\n", pcRxBuffer); 00312 } 00313 pcRxBuffer[0] = 'g'; 00314 errorValue = 0; 00315 } 00316 if(pcRxBuffer[0] == 's') { //save data string 00317 allowDisplayTime = true; 00318 pc.printf("Enter text string to save: "); 00319 pcClrLineBuf(); 00320 do { 00321 #ifdef RTOS_H 00322 Thread::wait(20); 00323 #else 00324 wait_ms(20); 00325 #endif 00326 } while((pcRxLine == false) && (pcRxEOB == false)); 00327 lockI2C(); 00328 errorValue = rtc.putUserRAM(pcRxBuffer, rtc_m, 128, pcRxQty + 2); 00329 unlockI2C(); 00330 if(errorValue) pc.printf("'Put' user RAM error: %d\r\n", errorValue); 00331 allowDisplayTime = false; 00332 pcRxBuffer[0] = 's'; 00333 errorValue = 0; 00334 } 00335 if(pcRxBuffer[0] == 't') Get3232Temp(); //display the DS3232's temperature 00336 if(pcRxBuffer[0] == 'z') { 00337 lockI2C(); 00338 rtc.LoadRTCRam(rtc_m); 00339 unlockI2C(); 00340 pc.printf("CRC16 value: 0x%04X\r\n", rtc.calculateCRC16(pcRxBuffer, rtc_m, 0x14, 0xea)); 00341 } 00342 if((pcRxBuffer[0] != 'a') && (pcRxBuffer[0] != 'A') && (pcRxBuffer[0] != 'b') 00343 && (pcRxBuffer[0] != 'B') && (pcRxBuffer[0] != 'c') && (pcRxBuffer[0] != 'g') 00344 && (pcRxBuffer[0] != 's') && (pcRxBuffer[0] != 't') && (pcRxBuffer[0] != 'z')) pc.printf("Entry Error!!\r\n"); 00345 pc.printf("\r\n"); 00346 pcClrLineBuf(); 00347 } 00348 #ifdef RTOS_H 00349 } //RTOS while loop 00350 #endif 00351 } 00352 00353 //--------------------------------------------------------------------------------------------------------------------------------------// 00354 00355 int main() { 00356 pc.baud(230400); 00357 ctTime = time(NULL); 00358 StartTime = ctTime; //get time we started up 00359 pc.printf("\r\n\r\nDS3232M demo Christmas-2014 K. Braun\r\n"); 00360 00361 //check for RTOS operation 00362 #ifdef RTOS_H 00363 pc.printf("RTOS installed...\r\n"); 00364 #else 00365 pc.printf("not using RTOS...\r\n"); 00366 #endif 00367 00368 //pc RX character callback interrupt 00369 pc.printf("Initializing Serial Port Rx Interrupt... \r\n"); 00370 pc.attach(&PcRxIRQ, pc.RxIrq); 00371 00372 pc.printf("Checking the mbed's RTC...\r\n"); 00373 #ifdef RTOS_H 00374 Thread::wait(1500); 00375 #else 00376 wait_ms(1500); 00377 #endif 00378 00379 ctTime = time(NULL); 00380 00381 //first, see if K64F's RTC already running 00382 if((StartTime == ctTime) || (ctTime <= 1000000000)) { 00383 pc.printf("*** mbed's local RTC is not initialized\r\n"); 00384 loadRTC(); 00385 StartTime = ctTime; 00386 00387 //now see if DS3232's clock needs to be set 00388 if(ctTime <= 1000000000) { 00389 pc.printf("*** Local RTC stopped, initializing the RTC. !!CHECK BATTERY!!\r\n"); 00390 pc.printf("*** Note: Time is incorrect, needs to be updated!!!\r\n"); 00391 00392 //set up the DS3232's clock 00393 if(SetRTC() != 0) pc.printf("Entry Error!!"); 00394 pcClrLineBuf(); 00395 } 00396 } 00397 00398 //sync up the mbed's time with the DS3232's time 00399 loadRTC(); 00400 StartTime = ctTime; 00401 pc.printf(" - RTC Start Time: "); 00402 PrintDateTime(); 00403 pc.printf(" - Day of Week: %s\r\n", timebuf_dow); //day of the week 00404 00405 //get the DS3232's temperature 00406 Get3232Temp(); 00407 00408 #ifdef RTOS_H 00409 //turn on the rest of the os threads 00410 pc.printf("Initializing os threads...\r\n"); 00411 Thread th3(cli_thread, NULL, osPriorityNormal); 00412 Thread::wait(300); 00413 #endif 00414 00415 int CheckTime = ctTime; 00416 pc.printf("Hit 'A' or 'a' - turn on/off the 32KHz output\r\n"); 00417 pc.printf("Hit 'B' or 'b' - turn on/off the 1Hz output (1Hz pin needs pull-up)\r\n"); 00418 pc.printf("Hit 'c' - change the date & time\r\n"); 00419 pc.printf("Hit 'g' - get data string from DS3232 user RAM\r\n"); 00420 pc.printf("Hit 's' - store data string in the DS3232 user RAM\r\n"); 00421 pc.printf("Hit 't' - get DS3232's temperature\r\n"); 00422 pc.printf("Hit 'z' - get user RAM CRC data\r\n"); 00423 pc.printf("Hit '^C' - reboot\r\n"); 00424 pc.printf("\r\n"); 00425 00426 //Ready!! 00427 while (true) { 00428 #ifdef RTOS_H 00429 Thread::wait(50); 00430 #else 00431 wait_ms(50); 00432 #endif 00433 UpdateTime(); 00434 if(CheckTime != ctTime) { 00435 CheckTime = ctTime; 00436 if(allowDisplayTime == false) PrintDateTime(); 00437 } 00438 #ifndef RTOS_H 00439 cli_thread(); 00440 #endif 00441 } 00442 }
Generated on Wed Jul 13 2022 18:59:27 by 1.7.2