How ds3231 works ?

Helloo world !
How ds3231 works ?
structural functional ?
and thanks .. .. :slight_smile:

How does it work, on what level?

From the perspective of the user, you install the battery, connect it to the I2C pins, and then your sketch talks to it using an RTC library (there are several to choose from) over I2C (using the Wire library); I think you have to first upload a sketch to set the time, and thereafter it keeps time and when your sketch asks for the time over I2C, the RTC returns it (see the examples for the library you're using to see how to do that).

In terms of how the chip works "under the hood" see the datasheet - it gives a detailed technical description, in far more detail than you need in order to use it (unless you needed to write the library yourself, but you don't because there already exist several, which are widely used and well maintained).

Here are pointers to a couple of useful starts for your research...

and

Happy reading

Hatem_Ad:
How ds3231 works ?

All explained in the datasheet;

1. The physical pin diagram of DS3231 RTC chip is depicted in Fig-1.
ds3231chip.png
Figure-1: Physical pin diagram of DS3231 RTC chip

2. The time-drift (slow/fast) of the DS3231 based Clock is +/- 2 minutes in 2-year (1 sec in 5 days). The RTC chip maintains such an accurate timing by virtue of a built-in 'temperature compensated crystal oscillator subsystem (Fig-2)' which provides 1 Hz timing signal for Clock, Calendar, and Alarms. The oscillator is always on when the chip is powered by the Vcc-pin (Fig-1).
ds3231osc.png
Figure-2: Temperature compensated internal crystal oscillator subsystem of DS3231 RTC chip

3. There are 'Seconds Register', 'Minutes Register', and 'Hours Register' inside the RTC chip to hold the current time of the day. In Fig-3, we have depicted the 'bit layout' of the 'Seconds Register' and 'Minutes Register'. The 'Hours Register' will be presented a short time later (Why? It is apparently complicated due to the presence of too many signal signatures!)

Figure-3: Bit layout of 'Seconds Register' and 'Minutes Register' of DS3231 RTC chip

(1) The Seconds Register holds the seconds of the clock (range: 00 - 59) in BCD (Binary Coded Decimal where a decimal digit is coded into 4-bit binary value) format. Thus, 00 seconds are coded as 0000000; 01 seconds are coded as 00000001; ...; 19 seconds are coded as 00011001; 20 seconds are coded as 00100000; ...; 59 seconds are coded as 01011001. Here, we observe that only 7-bit is good enough to hold the range (00 - 59) of the seconds of the clock; accordingly, the size of the Seconds Register is 7-bit (Fig-3); the lower 4-bit accommodate the value 0-9 (0000 - 1001) with positional weight of 1 (one) and the upper 3-bit accommodate the value 0-5 (000 - 101) with positional weight of 10 (ten). For example: assume that the current content of the Seconds Register is 0101001. What is the value of seconds? It is: (010)210 + (1001)21 = 210 + 91 = 29.

(2) Explanations similar to Step-3(1) can be extended for the description of the Minutes Register.

4. In this simple operation of DS3231 RTC chip using pre-fabricated module, we will set the initial time (only minutes and seconds) into the 'Minutes Register' and 'Seconds Register' of the RTC. After that the Clock will be at running condition; we will read the current values of minutes and seconds from the RTC chip and will display them on the top line of the LCD.
rtc3231-21y.png
Figure-4: Connection diagram among DS3231 RTC Module, UNO, I2CLCD, and Serial Monitor

(1) Let us connect the DS32131 RTC Module and I2CLCD with UNO as per Fig-4.

(2) DS3231 is an I2C Bus oriented device with 7-bit I2C Bus address 0x68 (0b1101000).

(3) Let us assign the following names (to be used in software) for the Seconds, Minutes and Hours Registers of the RTC:
bcdSeconds
bcdMinutes
bcdHours

(4) Let us upload the following sketch and observe that the Clock is advancing in the LCD. (Forget the Hours readings).

#include<Wire.h>
#define deviceAddress 0b1101000 //0x68
#include<LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  Serial.begin(9600);
  Wire.begin();   //I2C Bus is formed/eanbaled
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0); //DP0 of Topline

  //--setting up intial time -- 00:54:23
  Wire.beginTransmission(deviceAddress); //START, Roll Cal
  Wire.write(0x00); //SEC Register address in Address Counter of RTC
  Wire.write(0x23); //data for SEC Register (23 sec = 0010 0011; BCD format)
  Wire.write(0x54); //data for MIN Register (54 Min = 0101 0100; BCD format)
  Wire.write(0x00); //data for HRS Register ignore it now
  Wire.endTransmission(); //Execute the above Tasks, ACK STOP
}

void loop()
{
  showTimeOnLCD();
}

void showTimeOnLCD()
{
  Wire.beginTransmission(deviceAddress); //START, Roll Cal
  Wire.write(0x00); //pointing SEC Register at address 0x00 (Fig-2)
  Wire.endTransmission(); //Execute the above queued data, ACK, STOP

  Wire.requestFrom(deviceAddress, 3);   //SEC, MIN, and HRS to read from RTC as BCD
  byte bcdSeconds = Wire.read();
  byte bcdMinutes = Wire.read();
  byte bcdHours = Wire.read();  //ignore Hours reading
  
  //---show Time on LCD---------------
  lcd.print("Time: ");
  lcd.print(bcdHours >> 4); lcd.print(bcdHours & 0x0F); lcd.print(':');
  lcd.print(bcdMinutes>> 4); lcd.print(bcdMinutes & 0x0F); lcd.print(':');
  lcd.print(bcdSeconds >> 4); lcd.print(bcdSeconds & 0x0F);
  lcd.setCursor(0, 0);  //re=position the cursor
}

5. Hours Register of DS3231 RTC Chip
ds3231hoursReg.png
Figure-5: Bit layout of Hours Register

(1) In 24-hour Clock Time format, there is no AM and PM. The conventional 11 PM (11 o'clock by the night) is indicated by the figure 23:00:00. The 12 PM is indicated by 00:00:00. T operate DS3231 i 24-hour clock time mode, we put Logic-low (0) at 'BIT 6 (Fig-5)' of the Hours Register during initialization. As a result, the bit layout of Hours Register becomes as:
ds3231hoursRegX.png
Figure-6: Bit layout of Hours Register in 24-hour clock time format

(2) The Hours Register holds the hours of the clock (range: 00 - 23) in BCD format. Thus, 00 hours are coded as 0000000; ...; 17 seconds are coded as 00010111;...; 23 hours are coded as 00100011. Here, we observe that only 6-bit is good enough to hold the range (00 - 23) of the hours of the clock; accordingly, the size of the hours Register is 6-bit (Fig-6); the lower 4-bit accommodate the value 0-9 (0000 - 1001) with positional weight of 1 (one); Bit 4 accommodates the value 0-1 (0 - 1) with positional weight of 10 (ten); BIT 5 accommodates the value 0-1 (0 - 1) with positional weight of 20 (twenty) . For example: assume that the current content of the hours Register is 100001. What is the value of hours? It is: (1)2*20 + (0)2*10 + (0001)2*1 = 20 + 0 + 1 = 21. The bits will remain confined to a pattern such that the sum of the positional values of the 'Hour Field', '10 Hour Field' and '20 Hour Field' will never exceed 23.

(3) Now, let us add the following line at the appropriate place of the codes of Step-4(4) to initialize the clock time in 24-hour format and set the initial hours at 23.

Wire.write(0x23); //24 hour clock time format with initial hours time set at 23.

(4) In 12-hour Clock Time format, there is AM and PM. To maintain 12-Hr Time (12:00:00 AM ---> 12:30:00 PM ---> 01:0:00 PM ---> 12:30:00 PM ---> 01:00:00 AM ---> ...), we need to put Logic-high at 'BIT 6' of Hours Register of Fig-5 during intialization. The RTC automatically maintains LL (logic-low) of LH (logic-high) at BIT 5 of Hours Register to indicate AM (PM). As a result, the bit layout of Hours Register becomes as:
ds3231hoursReg12x.png
Figure-7: Bit layout of Hours Register in 12-hour clock time format

(5) Now, let us add the following line at the appropriate place of the codes of Step-4(4) to initialize the clock time in 12-hour format and set the initial hours at 12.

Wire.write(0x52); //12-Hr clock time format with initial hours time set at 12 (0101 0010).

(6) Add the following lines at the appropriate place of the codes of Step-4(4) so that the Hour of 12-hour clock time appear correctly on the LCD.

lcd.print((bcdHours>>4) & 0b00000001); lcd.print(bcdHours & 0b00001111); //see Fig-7

(7) Let us add the following line at the appropriate place of the codes of Step-4(4) to read BIT 5 (AM/PM) of Fig-7 and accordingly show AM (PM) along with current 12-Hr time on LCD.

if(bitRead(bcdHours, 5) == LOW)
  {
    lcd.print(" AM");
  }
  else
  {
    lcd.print(" PM");
  }

ds3231osc.png

ds3231chip.png

ds3231MinSecReg.png

rtc3231-21y.png

ds3231hoursReg.png

ds3231hoursRegX.png

ds3231hoursReg12x.png

6. Showing Current Date (Day: day/month/year) at bottom line of LCD
(1) Bit layout for the BCD formatted Day, Month, and Year Registers
ds3231DateReg.png
Figure-8: Bit layout for the BCD formatted day, month, and year registers.

(2) Day Register:
There are 7 days in a week. Let us accept that Sunday is the 1st day; Monday is the 2nd day; Tuesday is the 3rd day; Wednesday is the 4th day; Thursday is the 5th day; Friday is the 6th day; Saturday is the 7th day. We may assign the following bit pattern at Bit-2 to Bit-0 positions of the Day Register (Fig-8) for the days of the week:

Bit-2 Bit-1 Bit-0 Name of the Day
0      0      1      Sunday
0      1      0      Monday
0      1      1      Tuesday
1      0      0      Wednesday
1      0      1      Thursday
1      1      0      Friday
1      1      1      Saturday

If we set [Bit-2:Bit-0] = 001 for Sunday, the 'bit pattern' will automatically assume '010' for Monday after the elapse of 24-hrs time period; after the next 24-hrs, the bit pattern will become 011 for Tuesday and so on. In fact, the day-of-week register increments at midnight. Inconsistent time and data entries would result is 'undefined operation' of the clock.

(3) Setting up initial date (day/Mon/Year) and then display the current date.

#include<Wire.h>
#define deviceAddress 0b1101000 //0x68
#include<LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
char dayOftheWeek[10];
byte bcdDay;

void setup()
{
  Serial.begin(9600);
  Wire.begin();   //TWI Bus is formed
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0); //DP0 of Topline

  //--setting up intial time -- 00:54:23
  Wire.beginTransmission(deviceAddress); //START, Roll Cal
  Wire.write(0x00); //SEC Register address in Address Counter of RTC
  Wire.write(0x27); //data for SEC Register (23 sec = 0010 0011)
  Wire.write(0x54); //data for MIN Register (54 Min = 0101 0100)
  Wire.write(0x52); //data for HRS Register for 12 hour clock time format 12:54:27
  Wire.write(0x06);    //Friday
  Wire.write(0x19);     //0001 1001
  Wire.write (0x04);      //Month : April
  Wire.write (0x19);      //year: 0001 1001 = 19---> 2019
  Wire.endTransmission(); //Execute the above Tasks, ACK STOP
}

void loop()
{
  showTimeOnLCD();
}

void showTimeOnLCD()
{
  Wire.beginTransmission(deviceAddress); //START, Roll Cal
  Wire.write(0x00); //set SEC Register address
  Wire.endTransmission(); //Execute the above queued data, ACK, STOP

  Wire.requestFrom(deviceAddress, 7);   //SEC, MIN, and HRS to read from RTC as BCD
  byte bcdSeconds = Wire.read();
  byte bcdMinutes = Wire.read();
  byte bcdHours = Wire.read();
  bcdDay   = Wire.read();
  byte bcdDate = Wire.read();
  byte bcdMon = Wire.read();
  byte bcdYr = Wire.read();

  //---show Time on LCD---------------
  lcd.print("Time:");
  lcd.print(bcdHours >> 4 & 0b00000001); lcd.print(bcdHours & 0x0F); lcd.print(':');
  lcd.print(bcdMinutes >> 4); lcd.print(bcdMinutes & 0x0F); lcd.print(':');
  lcd.print(bcdSeconds >> 4); lcd.print(bcdSeconds & 0x0F);
  if (bitRead(bcdHours, 5) == LOW)
  {
    lcd.print(" AM");
  }
  else
  {
    lcd.print(" PM");
  }

  {
    //---show: day/month/year----
    lcd.setCursor(0, 1);
   //  lcd.print("Date:");
    getDay(bcdDay);
    lcd.print(dayOftheWeek);
    lcd.print(" :");
    lcd.print(bcdDate >> 4 & 0b00000011); lcd.print(bcdDate & 0x0F); lcd.print('/');
    lcd.print(bcdMon >> 4 & 0b00000001); lcd.print(bcdMon & 0x0F); lcd.print('/');
    lcd.print("20"); lcd.print(bcdDate >> 4 & 0b00000011); lcd.print(bcdDate & 0x0F); 
  }
  lcd.setCursor(0, 0);
}

void getDay(byte x)
{
  //lcd.print(x);
  switch (x)
  {
    case 0x01:
      {
        strcpy(dayOftheWeek, "Sun");
        break;
      }
    case 0x02:
      {
        strcpy(dayOftheWeek, "Mon");
        break;
      }
    case 0x03:
      {
        strcpy(dayOftheWeek, "Tue");
        break;
      }
    case 0x04:
      {
        strcpy(dayOftheWeek, "Wed");
        break;
      }
    case 0x05:
      {
        strcpy(dayOftheWeek, "Thu");
        break;
      }
    case 0x06:
      {
        strcpy(dayOftheWeek, "Fri");
        break;
      }
    case 0x07:
      {
        strcpy(dayOftheWeek, "Sat");
        break;
      }
  }
}

7. Handling DSD3231 RTC Operation using Library Functions
...

8. Function of VBAT pin of DS3231 Chip
...

ds3231DateReg.png