temtronic
Joined: 01 Jul 2010 Posts: 8892 Location: Greensville,Ontario
|
Basic DS3231 driver |
Posted: Tue Apr 13, 2021 4:49 am |
|
|
Below is a basic driver for the DS3231 RTC chip, essentially modiifed DS1307 code, so not all features, but it does set/get time info.
Code: |
////////////////////////////////////////////////////////////////////////////////
/// jay_rtc3231 from jay_DS1307.C ///
/// Driver for Real Time Clock ///
// ds3231_init() - Enable oscillator without clearing the seconds register -///
// enable square wave output at 1Hz
// ds3231_set_date_time(year,mth,day,dow,hrs,min,sec) Set the date/time ///
// ds3231_get_date_time(year,mth,day,dow,hrs,min,sec) Get the date/time
// ds3231_get_date(year,mth,day,dow) Get the date ///
//
// ds3231_get_time(hrs,min,sec) Get the time ///
//setup RTC pins
#ifndef RTC_SDA
#define RTC_SDA PIN_B1
#define RTC_SCL PIN_B2
#endif
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)
BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);
void ds3231_init(void)
{
BYTE seconds = 0;
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_start();
i2c_write(0xD1); // RD from RTC
seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
i2c_stop();
seconds &= 0x7F;
delay_us(3);
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x0E); // point to Control Register
i2c_write(0b01000000); // Enable squarewave output pin
i2c_stop();
}
void ds3231_set_date_time(BYTE rtcyer, BYTE rtcmth, BYTE rtcday, BYTE rtcdow, BYTE rtchrs, BYTE rtcmin, BYTE rtcsec)
{
rtcsec &= 0x7F;
rtchrs &= 0x3F;
i2c_start();
i2c_write(0xD0); // I2C write address
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_write(bin2bcd(rtcsec)); // REG 0
i2c_write(bin2bcd(rtcmin)); // REG 1
i2c_write(bin2bcd(rtchrs)); // REG 2
i2c_write(bin2bcd(rtcdow)); // REG 3
i2c_write(bin2bcd(rtcday)); // REG 4
i2c_write(bin2bcd(rtcmth)); // REG 5
i2c_write(bin2bcd(rtcyer)); // REG 6
i2c_stop();
}
void ds3231_get_time(BYTE &rtchrs, BYTE &rtcmin, BYTE &rtcsec)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1);
rtcsec = bcd2bin(i2c_read() & 0x7f);
rtcmin = bcd2bin(i2c_read() & 0x7f);
rtchrs = bcd2bin(i2c_read(0) & 0x3f);
i2c_stop();
}
void ds3231_get_date(BYTE &rtcyer, BYTE &rtcmth, BYTE &rtcday, BYTE &rtcdow)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x03); // Start at REG 3 - Day of week
i2c_start();
i2c_write(0xD1);
rtcdow = bcd2bin(i2c_read() & 0x7f); // REG 3
rtcday = bcd2bin(i2c_read() & 0x3f); // REG 4
rtcmth = bcd2bin(i2c_read() & 0x1f); // REG 5
rtcyer = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
}
void ds3231_get_date_time(BYTE &rtcyer, BYTE &rtcmth, BYTE &rtcday, BYTE &rtcdow, BYTE &rtchrs, BYTE &rtcmin, BYTE &rtcsec)
{
i2c_start();
i2c_write(0xD0); // WRITE cmd
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1); // READ cmd
rtcsec = bcd2bin(i2c_read() & 0x7f); // REG 0
rtcmin = bcd2bin(i2c_read() & 0x7f); // REG 1
rtchrs = bcd2bin(i2c_read() & 0x3f); // REG 2
rtcdow = bcd2bin(i2c_read() & 0x7f); // REG 3
rtcday = bcd2bin(i2c_read() & 0x3f); // REG 4
rtcmth = bcd2bin(i2c_read() & 0x1f); // REG 5
rtcyer = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
}
BYTE bin2bcd(BYTE binary_value)
{
BYTE temp;
BYTE retval;
temp = binary_value;
retval = 0;
while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(temp >= 10)
{
temp -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += temp;
break;
}
}
return(retval);
}
// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
BYTE temp;
temp = bcd_value;
// Shifting upper digit right by 1 is same as multiplying by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;
// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
//read DS3231 temerature sensor
void ds3231_get_temp(BYTE &rtctms, BYTE &rtctls)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x11); // Start at temperature MSB
i2c_start();
i2c_write(0xD1);
rtctms = i2c_read();
rtctls = i2c_read(0);
i2c_stop();
}
// returns chip temperature
// Temperature is stored in hundredths C (output value of "3125" equals 31.25 °C).
unsigned int16 Get_RTC_Temperature()
{
char t_msb, t_lsb;
unsigned int16 c_temp;
I2C_START();
I2C_WRITE(0xd0);
I2C_WRITE(0x11);
I2C_START();
I2C_WRITE(0xd1);
t_msb = I2C_READ(1);
t_lsb = I2C_READ(0);
I2C_STOP();
c_temp = (unsigned int16)t_msb << 2 | t_lsb >> 6;
if(t_msb & 0x80)
c_temp |= 0xFC00;
return c_temp * 25;
}
void ds3231_set_RAM(BYTE &rtcrm7,BYTE &rtcrm8,BYTE &rtcrm9,BYTE &rtcrmA,BYTE &rtcrmB,BYTE &rtcrmC,BYTE &rtcrmD)
{
i2c_start();
i2c_write(0xD0); // I2C write address
i2c_write(0x07); // Start at REG 7 'alarm data'
i2c_write(rtcrm7); // REG 7
i2c_write(rtcrm8); // REG 8
i2c_write(rtcrm9); // REG 9
i2c_write(rtcrmA); // REG A
i2c_write(rtcrmB); // REG B
i2c_write(rtcrmC); // REG C
i2c_write(rtcrmD); // REG D
i2c_stop();
}
void ds3231_get_RAM(BYTE &rtcrm7,BYTE &rtcrm8,BYTE &rtcrm9,BYTE &rtcrmA,BYTE &rtcrmB,BYTE &rtcrmC,BYTE &rtcrmD)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x07); // Start at REG 7 - 'alarm data'
i2c_start();
i2c_write(0xD1);
rtcrm7 = i2c_read(); // read all 7 bytes of RTC RAM
rtcrm8 = i2c_read(); // aka alarm bits
rtcrm9 = i2c_read(); // and bytes
rtcrmA = i2c_read();
rtcrmB = i2c_read();
rtcrmC = i2c_read();
rtcrmD = i2c_read(0);
i2c_stop();
}
|
|
|