|
9. DS3231 I2C real-time clock
The DS3231 is a low-cost, extremely accurate I²C real-time clock (RTC) with an integrated temperature-compensated crystal oscillator (TCXO) and crystal. The device incorporates a battery input, and maintains accurate timekeeping when main power to the device is interrupted. The integration of the crystal resonator enhances the long-term accuracy of the device as well as reduces the piece-part count in a manufacturing line. The DS3231 is available in commercial and industrial temperature ranges, and is offered in a 16-pin, 300-mil SO package.
The RTC maintains seconds, minutes, hours, day, date, month, and year information. The date at the end of the month is automatically adjusted for months with fewer than 31 days, including corrections for leap year. The clock operates in either the 24-hour or 12-hour format with an active-low AM/PM indicator. Two programmable time-of-day alarms and a programmable square-wave output are provided. Address and data are transferred serially through an I²C bidirectional bus.
A precision temperature-compensated voltage reference and comparator circuit monitors the status of VCC to detect power failures, to provide a reset output, and to automatically switch to the backup supply when necessary. Additionally, the active-low RST pin is monitored as a pushbutton input for generating a µP reset.
Key Features
- Highly Accurate RTC Completely Manages All Timekeeping Functions
- Real-Time Clock Counts Seconds, Minutes, Hours,
Date of the Month, Month, Day of the Week, and
Year, with Leap-Year Compensation Valid Up to 2100
- Accuracy ±2ppm from 0°C to +40°C
- Accuracy ±3.5ppm from -40°C to +85°C
- Digital Temp Sensor Output: ±3°C Accuracy
- Register for Aging Trim
- Active-Low RST Output/Pushbutton Reset Debounce Input
- Two Time-of-Day Alarms
- Programmable Square-Wave Output Signal
- Simple Serial Interface Connects to Most Microcontrollers
- Fast (400kHz) I2C Interface
- Battery-Backup Input for Continuous Timekeeping
- Low Power Operation Extends Battery-Backup Run Time
- 3.3V Operation
- Operating Temperature Ranges: Commercial (0°C to +70°C) and Industrial (-40°C to +85°C)
- Underwriters Laboratories® (UL) Recognized
Connect DS3231 aan een Arduino Mega
Bij de Arduino Mega de pinnen D20 en D21 zijn voor data en clock.
DS3231 |
Arduino Mega |
SCL |
D21 |
SDA |
D20 |
VCC |
5V of 3.3V |
GND |
GND |
Code
Functies:
byte decToBcd(byte val)
Conversie decimaal nummer naar binary code decimal
byte bcdToDec(byte val)
Conversie binaryy code decimal naar decimaal nummer.
void setup()
Initieel de tijd van de DS3231 zetten.
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
Zet de tijd van de DS3231 (7 bytes, I2C adres 0x68, byte 0, 2e register
dayofweek: zondag => 1
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
Leest de tijd uit.
void displayTime()
Laat de tijd zien. Indit geval met serial.print.
byte DS3231_get_MSB()
Haalt de temperatuur voor de komma op.
byte DS3231_get_LSB()
Haalt de temeratuur na de komma op.
void displayTemp()
Laat de temperatuur zien met serial.print
void loop()
Haalt om de seconde de data op en laat ze in de monitor zien.
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
#define DS3231_TEMPERATURE_MSB 0x11
#define DS3231_TEMPERATURE_LSB 0x12
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
void setup()
{
Wire.begin();
Serial.begin(9600);
// set the initial time here:
// DS3231 seconds, minutes, hours, day, date, month, year
setDS3231time(30, 37, 15, 2, 7, 3, 16);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
{
// sets time and date data to DS3231
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(second)); // set seconds
Wire.write(decToBcd(minute)); // set minutes
Wire.write(decToBcd(hour)); // set hours
Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
Wire.write(decToBcd(month)); // set month
Wire.write(decToBcd(year)); // set year (0 to 99)
Wire.endTransmission();
}
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void displayTime()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS3231
readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
// send it to the serial monitor
Serial.print(hour, DEC);
// convert the byte variable to a decimal number when displayed
Serial.print(":");
if (minute<10)
{
Serial.print("0");
}
Serial.print(minute, DEC);
Serial.print(":");
if (second<10)
{
Serial.print("0");
}
Serial.print(second, DEC);
Serial.print(" ");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.print(" Day of week: ");
switch(dayOfWeek){
case 1:
Serial.println("Sunday");
break;
case 2:
Serial.println("Monday");
break;
case 3:
Serial.println("Tuesday");
break;
case 4:
Serial.println("Wednesday");
break;
case 5:
Serial.println("Thursday");
break;
case 6:
Serial.println("Friday");
break;
case 7:
Serial.println("Saturday");
break;
}
}
byte DS3231_get_MSB()
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(DS3231_TEMPERATURE_MSB);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 1);
return Wire.read();
}
byte DS3231_get_LSB()
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(DS3231_TEMPERATURE_LSB);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 1);
return Wire.read() >> 6;
}
void displayTemp()
{
byte temp_msb = DS3231_get_MSB();
byte temp_lsb = DS3231_get_LSB();
Serial.print(temp_msb);
switch(temp_lsb){
case 0:
Serial.println(".00");
break;
case 1 :
Serial.println(".25");
break;
case 2:
Serial.println(".50");
break;
case 3:
Serial.println(".75");
break;
}
}
void loop()
{
displayTime(); // display the real-time clock data on the Serial Monitor,
displayTemp();
delay(1000); // every second
}
|