Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: ds3232m mbed mbed-rtos
main.cpp
- Committer:
- loopsva
- Date:
- 2014-12-23
- Revision:
- 2:958004aa28a4
- Parent:
- 1:c891c3930f4e
- Child:
- 3:f0eb506d4add
File content as of revision 2:958004aa28a4:
#include "mbed.h"
//#include "rtos.h" //mbed rtos - uncomment to make RTOS available
#include "ds3232m.h" //Maxim RTC
RawSerial pc(USBTX, USBRX); //onsole interface
#ifdef RTOS_H
Mutex MutexI2C0; //lock/unlock I2C requests
#endif //RTOS_H
#define SDA0 PTE25
#define SCL0 PTE24
ds3232m rtc(SDA0, SCL0, 400000); //Maxim real time clock
//--------------------------------------------------------------------------------------------------------------------------------------//
// Time variables
time_t ctTime; //time structure
int DST = 1; //Daylight Saving Time (or as defined in .ini file)
int TZone = -8; //Time Zone from UTC (or as defined in .ini file)
char timebuf_hms[10]; //local time format buffer - 21:16:43
char timebuf_dMyy[14]; //local time format buffer - 01-Apr-2014
char timebuf_dow[1]; //local time format buffer - 5
int StartTime = 0; //time we powered up
bool allowDisplayTime = false; //used to stop displaying date/time when entering data from the console
//--------------------------------------------------------------------------------------------------------------------------------------//
//Variables for USB Serial Port RX
uint32_t pcRxQty = 0; //RX data counter/pointer
char pcRxBuffer[128]; //RX data buffer
bool pcRxLine = false; //CR or LF detected (end of line)
bool pcRxEOB = false; //RX buffer is full!!! cannot accept any more characters
char inchar = 0; //RX input character
//--------------------------------------------------------------------------------------------------------------------------------------//
// This function is called when a character goes into the RX buffer.
#define DOUPONELINE "\033[1A"
#define BS 0x08 //ascii backspace
#define CR 0x0d //ascii CR
#define LF 0x0a //ascii LF
#define ticC 0x03 //ascii control C
#define DEGC_DEGF_FLOAT 9.0 / 5.0 + 32.0
void PcRxChar(char inchar) {
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
if(inchar == LF) pc.printf(" %c %c", BS, BS);
if(inchar == BS) {
if(pcRxQty == 0) {
pcRxBuffer[pcRxQty] = 0;
} else {
pc.printf("%c %c", BS, BS);
pcRxQty--;
pcRxBuffer[pcRxQty] = 0;
}
} else if((inchar == CR) || (inchar == LF)) {
pcRxLine = true;
pc.printf("\r\n");
} else if(inchar == ticC) {
NVIC_SystemReset();
} else {
if(pcRxQty < (sizeof(pcRxBuffer) - 2)) {
pcRxBuffer[pcRxQty] = inchar;
pcRxQty++;
pcRxBuffer[pcRxQty] = 0;
pc.printf("%c", pcRxBuffer[pcRxQty - 1]);
} else {
pc.printf ("\r\n*** pcRxBuffer is full!!\r\n");
pcRxEOB = true;
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------------//
// Read received chars from USB UART interrupt
void PcRxIRQ(void){
#if defined(TARGET_KL25Z)
NVIC_DisableIRQ(UART0_IRQn); // n=0, 1 or 2 Disable Rx interrupt on kl25z
#endif
#if defined(TARGET_K64F)
NVIC_DisableIRQ(UART0_RX_TX_IRQn); // n=0, 1 or 2 Disable Rx interrupt on k64f
#endif
#if defined(TARGET_LPC1768)
LPC_UART0->IER = 0; //Disable Rx interrupt on mbed1768
#endif
while (pc.readable()) {
inchar = pc.getc(); //<<<<< broken here!!!! //read data from USB
PcRxChar(inchar); //go process char
}
#if defined(TARGET_KL25Z)
NVIC_EnableIRQ(UART0_IRQn); // n=0, 1 or 2 Re-enable Rx interrupt on kl25z
#endif
#if defined(TARGET_K64F)
NVIC_EnableIRQ(UART0_RX_TX_IRQn); // n=0, 1 or 2 Re-enable Rx interrupt on k64f
#endif
#if defined(TARGET_LPC1768)
LPC_UART0->IER = 1; //RE-enable Rx interrupt on mbed1768
#endif
}
//--------------------------------------------------------------------------------------------------------------------------------------//
//clear RxData buffer with all 00's and clear flags
void pcClrLineBuf() {
pcRxQty = 0; // data counter/pointer
for(int i = 0; i < (sizeof(pcRxBuffer) - 1); i++) pcRxBuffer[i] = 0; // clear out rx buffer
pcRxLine = false;
pcRxEOB = false;
}
//--------------------------------------------------------------------------------------------------------------------------------------//
// Update time display values
void UpdateTimeRegs() {
strftime(timebuf_dMyy, 14, "%d-%b-%Y", localtime(&ctTime));
strftime(timebuf_hms, 10, "%H:%M:%S", localtime(&ctTime));
strftime(timebuf_dow, 1, "%u", localtime(&ctTime));
}
void UpdateTime() {
ctTime = time(NULL) + ((TZone + DST) * 3600); //timezone and dst offsets
UpdateTimeRegs();
}
//--------------------------------------------------------------------------------------------------------------------------------------//
// display current local date and time
void PrintDateTime() {
pc.printf("%sDate: %s ", DOUPONELINE, timebuf_dMyy);
pc.printf("Time: %s \r\n", timebuf_hms);
}
//--------------------------------------------------------------------------------------------------------------------------------------//
//Manually set the date and time
ds3232m::Time_rtc rtc_m = {};
struct tm t;
bool SetRTC() {
pc.printf("Enter current date and time:\n");
pc.printf("MM DD YY HH MM SS[enter]\n");
pcClrLineBuf();
//wait for string above
do{
#ifdef RTOS_H
Thread::wait(10);
#else
wait_ms(10);
#endif
} while((pcRxLine == false) && (pcRxEOB == false));
//load up the time structure
t.tm_year = (2000 + ((pcRxBuffer[6] - '0') * 10) + pcRxBuffer[7] - '0');
t.tm_mon = (((pcRxBuffer[0] - '0') * 10) + pcRxBuffer[1] - '0');
t.tm_mday = (((pcRxBuffer[3] - '0') * 10) + pcRxBuffer[4] - '0');
t.tm_hour = (((pcRxBuffer[9] - '0') * 10) + pcRxBuffer[10] - '0');
t.tm_min = (((pcRxBuffer[12] - '0') * 10) + pcRxBuffer[13] - '0');
t.tm_sec = (((pcRxBuffer[15] - '0') * 10) + pcRxBuffer[16] - '0');
//adjust for tm structure required values
t.tm_year = t.tm_year - 1900;
t.tm_mon = t.tm_mon - 1;
t.tm_wday = t.tm_wday & 7;
//if error exists, exit without changing time
if(t.tm_year < 113) return(32);
if(t.tm_mon > 12) return(16);
if(t.tm_mday > 31) return(8);
if(t.tm_hour > 23) return(4);
if(t.tm_min > 59) return(2);
if(t.tm_sec > 59) return(1);
//set up the DS3232's RTC
rtc_m.sec = t.tm_sec;
rtc_m.min = t.tm_min;
rtc_m.hour = t.tm_hour;
rtc_m.wday = t.tm_wday;
rtc_m.date = t.tm_mday;
rtc_m.mon = t.tm_mon + 1;
rtc_m.year = t.tm_year + 1900;
rtc.setTime(rtc_m); //(time structure)
//set the mbed's time
time_t ctTime = mktime(&t);
//reset system up time since it will be out of whack once the time is updated
StartTime = ctTime; //have to change sysuptime now
ctTime = ctTime - (TZone + DST) * 3600; //take out local time
set_time(ctTime);
UpdateTime();
return(0);
}
//--------------------------------------------------------------------------------------------------------------------------------------//
// Load the local mbed-RTC from that external DS3232 RTC
void loadRTC() {
//get data from DS3232
rtc.getTime(rtc_m);
t.tm_sec = rtc_m.sec;
t.tm_min = rtc_m.min;
t.tm_hour = rtc_m.hour;
t.tm_mday = rtc_m.date;
t.tm_mon = rtc_m.mon - 1;
t.tm_year = rtc_m.year - 1900;
//set the mbed's time
time_t ctTime = mktime(&t);
ctTime = ctTime - (TZone + DST) * 3600; //take out local time
set_time(ctTime);
UpdateTime();
}
//--------------------------------------------------------------------------------------------------------------------------------------//
// Pull the temperature out of the DS3232 RTC
void Get3232Temp() {
pc.printf("%c", BS);
if(rtc.startTempCycle() == true) {
pc.printf(" - DS3232M start converstion ok \r\n");
} else {
pc.printf(" - DS3232M start converstion BUSY!!! \r\n");
}
//wait for DS3232 temperature conversion to finish
int i = 80;
for(i = 80; i > 0; i--) {
#ifdef RTOS_H
Thread::wait(20);
#else
wait_ms(20);
#endif
if((rtc.checkTempBusy()) == true) break;
}
//timed out or display temperature
if(i > 0) {
float ds3232tempC = rtc.getTemperature();
pc.printf(" - DS3232M Temperature: %.2fC %.1fF\r\n", ds3232tempC, ds3232tempC * DEGC_DEGF_FLOAT);
} else {
pc.printf("*** DS3232M Temperature timeout!!!!\r\n");
}
}
//--------------------------------------------------------------------------------------------------------------------------------------//
// Checking for characters to execute commands from. It's a thread if RTOS is used.
#ifdef RTOS_H
void cli_thread(void const *argument) {
pc.printf(" - Starting CLI RTOS thread\r\n");
while (true) { //while loop only for RTOS
Thread::wait(73);
#else
void cli_thread() {
#endif
if(pcRxQty != 0) {
pc.printf("\r\n");
if(pcRxBuffer[0] == 'A') rtc.set32KhzOutput(true, false); //turn on 32KHz output
if(pcRxBuffer[0] == 'a') rtc.set32KhzOutput(false, false); //turn off 32KHz output
if(pcRxBuffer[0] == 'B') rtc.set1hzOutput(true, false); //turn on 1Hz output
if(pcRxBuffer[0] == 'b') rtc.set1hzOutput(false, false); //turn off 1Hz output
if(pcRxBuffer[0] == 'c') {
allowDisplayTime = true;
SetRTC(); //change DS3232 time
allowDisplayTime = false;
pcRxBuffer[0] = 'c';
}
uint16_t errorValue = 0;
if(pcRxBuffer[0] == 'g') { //get and display stored data string
errorValue = rtc.getUserRAM(pcRxBuffer, 128, 126);
if(errorValue) {
pc.printf("'Get' user RAM error: %d\r\n", errorValue);
} else if(pcRxBuffer[0] == NULL) {
pc.printf("User RAM empty!!\r\n");
} else {
//pcRxBuffer[31] = NULL; //guarantee that the string max length is 32 bytes
pc.printf("%s\r\n", pcRxBuffer);
}
pcRxBuffer[0] = 'g';
errorValue = 0;
}
if(pcRxBuffer[0] == 's') { //save data string
allowDisplayTime = true;
pc.printf("Enter text string to save: ");
pcClrLineBuf();
do {
#ifdef RTOS_H
Thread::wait(20);
#else
wait_ms(20);
#endif
} while((pcRxLine == false) && (pcRxEOB == false));
errorValue = rtc.putUserRAM(pcRxBuffer, 128, pcRxQty + 2);
if(errorValue) pc.printf("'Put' user RAM error: %d\r\n", errorValue);
allowDisplayTime = false;
pcRxBuffer[0] = 's';
errorValue = 0;
}
if(pcRxBuffer[0] == 't') Get3232Temp(); //display the DS3232's temperature
if(pcRxBuffer[0] == 'z') {
rtc.LoadRTCRam();
pc.printf("CRC16 value: 0x%04X\r\n", rtc.calculateCRC16(rtc.RTCbuffer, 0x14, 0xea));
}
if((pcRxBuffer[0] != 'a') && (pcRxBuffer[0] != 'A') && (pcRxBuffer[0] != 'b')
&& (pcRxBuffer[0] != 'B') && (pcRxBuffer[0] != 'c') && (pcRxBuffer[0] != 'g')
&& (pcRxBuffer[0] != 's') && (pcRxBuffer[0] != 't') && (pcRxBuffer[0] != 'z')) pc.printf("Entry Error!!\r\n");
pc.printf("\r\n");
pcClrLineBuf();
}
#ifdef RTOS_H
} //RTOS while loop
#endif
}
//--------------------------------------------------------------------------------------------------------------------------------------//
int main() {
pc.baud(230400);
ctTime = time(NULL);
StartTime = ctTime; //get time we started up
pc.printf("\r\n\r\nDS3232M demo 23-DEC-2014 K. Braun\r\n");
//check for RTOS operation
#ifdef RTOS_H
pc.printf("RTOS installed...\r\n");
#else
pc.printf("not using RTOS...\r\n");
#endif
//pc RX character callback interrupt
pc.printf("Initializing Serial Port Rx Interrupt... \r\n");
pc.attach(&PcRxIRQ, pc.RxIrq);
pc.printf("Checking the mbed's RTC...\r\n");
#ifdef RTOS_H
Thread::wait(1500);
#else
wait_ms(1500);
#endif
ctTime = time(NULL);
//first, see if K64F's RTC already running
if((StartTime == ctTime) || (ctTime <= 1000000000)) {
pc.printf("*** mbed's local RTC is not initialized\r\n");
loadRTC();
StartTime = ctTime;
//now see if DS3232's clock needs to be set
if(ctTime <= 1000000000) {
pc.printf("*** Local RTC stopped, initializing the RTC. !!CHECK BATTERY!!\r\n");
pc.printf("*** Note: Time is incorrect, needs to be updated!!!\r\n");
//set up the DS3232's clock
if(SetRTC() != 0) pc.printf("Entry Error!!");
pcClrLineBuf();
}
}
//sync up the mbed's time with the DS3232's time
loadRTC();
StartTime = ctTime;
pc.printf(" - RTC Start Time: ");
PrintDateTime();
pc.printf(" - Day of Week: %s\r\n", timebuf_dow); //day of the week
//get the DS3232's temperature
Get3232Temp();
#ifdef RTOS_H
//turn on the rest of the os threads
pc.printf("Initializing os threads...\r\n");
Thread th3(cli_thread, NULL, osPriorityNormal);
Thread::wait(300);
#endif
int CheckTime = ctTime;
pc.printf("Hit 'A' or 'a' - turn on/off the 32KHz output\r\n");
pc.printf("Hit 'B' or 'b' - turn on/off the 1Hz output (1Hz pin needs pull-up)\r\n");
pc.printf("Hit 'c' - change the date & time\r\n");
pc.printf("Hit 'g' - get data string from DS3232 user RAM\r\n");
pc.printf("Hit 's' - store data string in the DS3232 user RAM\r\n");
pc.printf("Hit 't' - get DS3232's temperature\r\n");
pc.printf("Hit 'z' - get user RAM CRC data\r\n");
pc.printf("Hit '^C' - reboot\r\n");
pc.printf("\r\n");
//Ready!!
while (true) {
#ifdef RTOS_H
Thread::wait(50);
#else
wait_ms(50);
#endif
UpdateTime();
if(CheckTime != ctTime) {
CheckTime = ctTime;
if(allowDisplayTime == false) PrintDateTime();
}
#ifndef RTOS_H
cli_thread();
#endif
}
}