MAXIM DS3231 accurate Real Time Clock Library

Dependents:   I2C-LCD-DHT22 wifigpslcd HomeStatus project ... more

Files at this revision

API Documentation at this revision

Comitter:
cromda
Date:
Sat Dec 22 19:23:19 2012 +0000
Child:
1:84ccc64067d8
Commit message:
MAXIM DS3231 RTC

Changed in this revision

DS3231.cpp Show annotated file Show diff for this revision Revisions of this file
DS3231.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DS3231.cpp	Sat Dec 22 19:23:19 2012 +0000
@@ -0,0 +1,132 @@
+#include "DS3231.h"
+
+DS3231::DS3231(PinName sda, PinName scl) : i2c(sda, scl)
+    {
+    } 
+    
+    
+// BCD to decimal conversion    
+int DS3231::bcd2dec(int k)
+    {return(((k&0xF0)>>4)*10+(k&0x0F));}
+    
+    
+// decimal to BCD conversion    
+int DS3231::dec2bcd(int k)
+    {return((k/10)*16+(k%10));}      
+    
+void DS3231::setI2Cfrequency(int frequency)
+    {i2c.frequency(frequency);
+    }
+    
+// read temperature from DS3231    
+float DS3231::readTemp()
+    {char buf[2];
+     buf[0]=DS3231_MSB_Temp;
+     int w=i2c.write(DS3231_Address,buf,1);
+     int r=i2c.read(DS3231_Address,buf,2);
+     error=((w!=0)||(r!=0));   
+     return(buf[0]+buf[1]/256.0);}   
+
+// decode time registers     
+void DS3231::decodeTime(int regHours, int regMinutes, int regSeconds,int *Hours, int *Minutes, int *Seconds)
+    {*Hours=bcd2dec(regHours);
+     *Minutes=bcd2dec(regMinutes);
+     *Seconds=bcd2dec(regSeconds);
+    }      
+     
+     
+// read time registers dand decode them to decimal     
+void DS3231::readTime(int *hours, int *minutes, int *seconds)
+    {char buf[3];
+     buf[0]=DS3231_Seconds;
+     int w=i2c.write(DS3231_Address,buf,1);
+     int r=i2c.read(DS3231_Address,buf,3);
+     decodeTime(buf[2],buf[1],buf[0],hours,minutes,seconds);    
+     error=((w!=0)||(r!=0));
+    }  
+    
+// set time register    
+void DS3231::setTime(int hours, int minutes, int seconds)
+    {writeRegister(DS3231_Seconds,dec2bcd(seconds));
+     writeRegister(DS3231_Minutes,dec2bcd(minutes));
+     writeRegister(DS3231_Hours,dec2bcd(hours));
+    }    
+    
+// decode date registers
+void DS3231::decodeDate(int regDate,int regMonth, int regYear, int *date, int *month, int *year)
+    {*date=bcd2dec(regDate);
+     int century=regMonth&128;
+     *month=bcd2dec(regMonth&127);
+     *year=bcd2dec(regYear);
+     if (century==0)         // only XXth and XXIst centuries allowed
+        {*year=*year+1900;}
+     else
+        {*year=*year+2000;}
+    }         
+    
+// read date registers    
+void DS3231::readDate(int *date, int *month, int *year)
+    {char buf[3];
+     buf[0]=DS3231_Date;
+     int w=i2c.write(DS3231_Address,buf,1);
+     int r=i2c.read(DS3231_Address,buf,3);
+     decodeDate(buf[0],buf[1],buf[2],date,month,year);            
+     error=((w!=0)||(r!=0));         
+    }     
+    
+// set the date registers
+void DS3231::setDate(int dayOfWeek, int date, int month, int year)
+    {writeRegister(DS3231_Date,dec2bcd(date));
+     writeRegister(DS3231_Day,dayOfWeek);
+     int century=0; // only XXth and XXIst centuries allowed
+     if (year<1900){year=1900;}
+     if (year>2099){year=2099;}
+     if (year<2000)
+        {year=year-1900;}
+     else
+        {year=year-2000;century=1;}   
+     writeRegister(DS3231_Month_Century,dec2bcd(month)+128*century);   
+     writeRegister(DS3231_Year,dec2bcd(year));
+    }     
+    
+// read date and time registers    
+void DS3231::readDateTime(int *dayOfWeek, int *date, int *month, int *year, int *hours, int *minutes, int *seconds)
+    {char buf[7];
+     buf[0]=DS3231_Seconds;
+     int w=i2c.write(DS3231_Address,buf,1);
+     int r=i2c.read(DS3231_Address,buf,7);
+     decodeTime(buf[2],buf[1],buf[0],hours,minutes,seconds);
+     *dayOfWeek=buf[3];
+     decodeDate(buf[4],buf[5],buf[6],date,month,year);
+     error=((w!=0)||(r!=0));     
+    }    
+    
+// read a register    
+int DS3231::readRegister(char reg)
+    {char buf[1];
+     buf[0]=reg;
+     int w=i2c.write(DS3231_Address,buf,1);
+     int r=i2c.read(DS3231_Address,buf,1);
+     error=((w!=0)||(r!=0));  
+     return(buf[0]);
+    }   
+
+// write a register    
+void DS3231::writeRegister(int reg,char byte)
+    {char buf[2];
+     buf[0]=reg;
+     buf[1]=byte;
+     int w=i2c.write(DS3231_Address,buf,2); 
+     error=(w!=0);   
+    }      
+    
+void DS3231::eraseOSF()
+    {int reg=readRegister(DS3231_Control_Status);
+     reg=reg&0x7F;
+     writeRegister(DS3231_Control_Status,reg);
+    }     
+    
+bool DS3231::OSF()
+    {int reg=readRegister(DS3231_Control_Status);
+    return(reg&DS3231_bit_OSF);
+    }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DS3231.h	Sat Dec 22 19:23:19 2012 +0000
@@ -0,0 +1,216 @@
+/** mbded library for driving the PMAXIM DS3231 Real Time Clock
+* datasheet link : http://datasheets.maximintegrated.com/en/ds/DS3231.pdf
+* breakout       : MACETECH ChronoDot V2.1 High Precision RTC
+* remi cormier 2012
+* WARNING : sda and sdl should be pulled up with 2.2k resistor
+*/
+
+/** Example code
+* @code
+// DS3231 Library test program
+// remi cormier 2012
+
+#include "mbed.h"
+#include "DS3231.h"
+
+Serial pc(USBTX, USBRX);
+
+int hour;
+int minute;
+int second;
+
+int dayOfWeek;
+int date;
+int month;
+int year;  
+   
+DS3231 RTC(p28,p27);
+
+
+int main()
+    {printf("\r\n\nDS3231 Library test program\r\nremi cormier 2012\r\n\n");
+    
+     RTC.setI2Cfrequency(400000);
+    
+     //RTC.writeRegister(DS3231_Aging_Offset,0); // uncomment to set Aging Offset 1LSB = approx. 0.1 ppm according from datasheet = 0.05 ppm @ 21 °C from my measurments
+      
+     int reg=RTC.readRegister(DS3231_Aging_Offset);
+     if (reg>127)
+        {reg=reg-256;}
+     pc.printf("Aging offset : %i\r\n",reg);
+         
+     pc.printf("OSF flag : %i",RTC.OSF());
+     pc.printf("\r\n");
+     
+     RTC.readDate(&date,&month,&year);
+     pc.printf("date : %02i-%02i-%02i",date,month,year);
+     pc.printf("\r\n");
+     
+     //RTC.setTime(19,48,45); // uncomment to set time
+     
+     RTC.readTime(&hour,&minute,&second);
+     pc.printf("time : %02i:%02i:%02i",hour,minute,second);
+     pc.printf("\r\n");
+     
+     //RTC.setDate(6,22,12,2012); // uncomment to set date
+     
+     RTC.readDateTime(&dayOfWeek,&date,&month,&year,&hour,&minute,&second);
+     pc.printf("date time : %i / %02i-%02i-%02i %02i:%02i:%02i",dayOfWeek,date,month,year,hour,minute,second);
+     pc.printf("\r\n");
+     
+     pc.printf("temperature :%6.2f",RTC.readTemp());
+     pc.printf("\r\n");
+    }
+* @endcode
+*/
+
+
+#include "mbed.h"
+
+#ifndef MBED_DS3231_H
+#define MBED_DS3231_H
+
+//DS3231 8 bit adress
+#define DS3231_Address          0xD0
+
+//DS3231 registers
+#define DS3231_Seconds          0x00
+#define DS3231_Minutes          0x01
+#define DS3231_Hours            0x02
+// DS3231 Hours bits
+#define DS3231_bit_AM_PM        0x20
+#define DS3231_bit_12_24        0x40
+
+#define DS3231_Day              0x03
+#define DS3231_Date             0x04
+#define DS3231_Month_Century    0x05
+#define DS3231_Year             0x06
+#define DS3231_Alarm1_Seconds   0x07
+#define DS3231_Alarm1_Minutes   0x08
+#define DS3231_Alarm1_Hours     0x09
+#define DS3231_Alarm1_Day_Date  0x0A
+#define DS3231_Alarm2_Minutes   0x0B
+#define DS3231_Alarm2_Hours     0x0C
+#define DS3231_Alarm_2_Day_Date 0x0D
+
+#define DS3231_Control          0x0E
+// DS3231 Control bits
+#define DS3231_bit_A1IE        1
+#define DS3231_bit_A2IE        2
+#define DS3231_bit_INTCN       4
+#define DS3231_bit_SQW_1Hz     0
+#define DS3231_bit_SQW_1024Hz  8
+#define DS3231_bit_SQW_4096Hz 16
+#define DS3231_bit_SQW_8192Hz 24
+#define DS3231_bit_CONV       32
+#define DS3231_bit_BBSQW      64
+#define DS3231_bit_EOSCb     128
+
+
+#define DS3231_Control_Status   0x0F
+// DS3231 Control/Status bits
+#define DS3231_bit_BSY     0x04
+#define DS3231_bit_EN32kHz 0x08
+#define DS3231_bit_OSF     0x80
+
+#define DS3231_Aging_Offset     0x10
+#define DS3231_MSB_Temp         0x11
+#define DS3231_LSB_Temp         0x12
+
+/* Interface to MAXIM DS3231 RTC */
+class DS3231
+    {public :
+     /** Create an instance of the DS3231 connected to specfied I2C pins
+     *
+     * @param sda The I2C data pin
+     * @param scl The I2C clock pin
+     */
+     DS3231(PinName sda, PinName scl);
+     
+     /** set I2C bus speed
+     * @param frequency : I2C clocl frequenct (Hz)
+     */
+     void setI2Cfrequency(int frequency);
+     
+     /** Read the temperature
+     *
+     * @return The temperature
+     */
+     float readTemp();
+     
+     /** Read the time registers
+     * @param hours
+     * @param minutes
+     * @param seconds
+     */
+     void readTime(int *hours, int *minutes, int *seconds);
+     
+     
+     /** Set the time registers
+     * @param hours
+     * @param minutes
+     * @param seconds
+     */
+     void setTime(int hours, int minutes, int seconds);
+     
+     /** Read the date registers
+     * @param date
+     * @param month
+     * @param year
+     */
+     void readDate(int *date, int *month, int *year);
+     
+     /** Set the date registers
+     * @param dayOfWeek : day of week
+     * @param date
+     * @param month
+     * @param year
+     */
+     void setDate(int dayOfWeek, int date, int month, int year);
+     
+     /** Read the date and time registers
+     * @param dayOfWeek : day of week
+     * @param date
+     * @param month
+     * @param year
+     * @param hours
+     * @param minutes
+     * @param seconds
+     */
+     void readDateTime(int *dayOfWeek, int *date, int *month, int *year, int *hours, int *minutes, int *seconds);
+     
+     /** Read a register
+     * @param reg : register address
+     * @return The register content
+     */     
+     int readRegister(char reg);
+     
+     /** Write to a register
+     * @param reg : register address
+     * @param The register content
+     */       
+     void writeRegister(int reg,char byte);
+     
+     /** set OSF (Oscillator Stop Flag) bit to 0 in Control Status register
+     * should be done just after power up DS3231
+     * OSF bit is automaticaly set to 1 when on power up or when the DS3231 oscillator stops
+     */
+     void eraseOSF();
+     
+     /** Return OSF bit. If true the oscillator stopped or the DS3231 just powered up
+     * @return The OSF bit
+     */
+     bool OSF();
+     
+     bool error;
+     
+     private :
+     I2C i2c;
+     int bcd2dec(int k); // bcd to decimal conversion
+     int dec2bcd(int k); // decimal to bcd conversion
+     void decodeTime(int regHours, int regMinutes, int regSeconds,int *Hours, int *Minutes, int *Seconds);
+     void decodeDate(int regDate,int regMonth, int regYear, int *date, int *month, int *year);
+    };
+
+
+#endif
\ No newline at end of file