DS3231 / AT24C32 Real-Time Clock (RTC)
The DS3231 is a highly accurate I²C real-time clock with an integrated temperature-compensated crystal oscillator, providing precise timekeeping and calendar functions, along with programmable alarms and square-wave output, suitable for applications requiring reliable timekeeping.

On this page
DS3231 / AT24C32 pinout
The DS3231 pinout includes I2C communication pins (SDA, SCL), power supply (VCC, VBAT), ground, interrupt/square wave output (INT/SQW), 32kHz output, and reset pin. It features a built-in temperature-compensated crystal oscillator (TCXO).
| Pin | Type | Description | Notes |
|---|---|---|---|
| VCC | Power | Primary power supply input (2.3V to 5.5V) | Main power source, wide voltage range |
| GND | Ground | Ground connection | Common ground |
| SDA | I2C Data | I2C Serial Data line | Bidirectional data line (requires pull-up) |
| SCL | I2C Clock | I2C Serial Clock line | Clock line (requires pull-up) |
| VBAT | Backup Power | Battery backup input (2.3V to 5.5V) | CR2032 battery for timekeeping during power loss |
| INT/SQW | Output | Interrupt or square wave output | Programmable alarm interrupt or square wave |
| 32KHz | Output | 32.768 kHz output | Optional 32kHz clock output |
| RST | Control | Reset input/output | Optional reset control (active low) |
Ultra-accurate RTC with built-in TCXO (Temperature-Compensated Crystal Oscillator)
Accuracy: ±2ppm (0°C to +40°C), ±3.5ppm (-40°C to +85°C)
Real-time clock: seconds, minutes, hours, day, date, month, year
Leap year compensation up to 2100
Two programmable time-of-day alarms
I2C interface with address 0x68
Operating voltage: 2.3V to 5.5V (both VCC and VBAT)
Integrated temperature sensor (±3°C accuracy)
No external crystal required (built-in TCXO)
Battery backup with automatic switchover
Wiring the DS3231 / AT24C32 to ESP32
Connect the DS3231 to your ESP32 via I2C (SDA and SCL pins). The module has a wide voltage range (2.3V to 5.5V) and includes a built-in temperature-compensated crystal oscillator for superior accuracy. A CR2032 battery provides backup power.
| DS3231 / AT24C32 pin | ESP32 pin | Purpose |
|---|---|---|
| VCC | 3.3V or 5V | Primary power supply (2.3V to 5.5V) |
| GND | GND | Ground connection |
| SDA | GPIO21 | I2C data line (with 4.7kΩ pull-up) |
| SCL | GPIO22 | I2C clock line (with 4.7kΩ pull-up) |
| VBAT | CR2032 Battery | Backup battery (3V) · optional |
| INT/SQW | GPIO (optional) | Interrupt/square wave output · optional |
| 32KHz | GPIO (optional) | 32kHz clock output · optional |
I2C address: 0x68 (same as DS1307, cannot coexist on same bus)
Works with both 3.3V and 5V (ESP32 uses 3.3V)
Pull-up resistors (4.7kΩ) required on SDA and SCL
Most modules include pull-up resistors and CR2032 battery holder
MUCH more accurate than DS1307 due to TCXO
Built-in temperature compensation eliminates crystal drift
No external crystal needed (TCXO integrated)
INT/SQW can trigger interrupts for alarms
Use RTClib or DS3231 library for Arduino/ESP32
Best choice for precision timekeeping applications
Often includes AT24C32 EEPROM (32KB) on same module
DS3231 / AT24C32 code examples
DS3231 / AT24C32 Arduino example
Copy#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(2023, 12, 4, 14, 30, 0)); // Set initial date/time
}
}
void loop() {
DateTime now = rtc.now();
Serial.print("Time: ");
Serial.print(now.hour());
Serial.print(":");
Serial.print(now.minute());
Serial.print(":");
Serial.println(now.second());
Serial.print("Date: ");
Serial.print(now.year());
Serial.print("/");
Serial.print(now.month());
Serial.print("/");
Serial.println(now.day());
delay(1000);
}This Arduino sketch demonstrates how to interface with the DS3231 RTC module using the RTClib library. In the setup() function, the RTC is initialized, and if it has lost power, the date and time are set. The loop() function retrieves the current time and date from the RTC and prints them to the Serial Monitor every second.
DS3231 / AT24C32 ESP-IDF example
Copy// Requires the esp-idf-lib DS3231 driver from the ESP Component Registry:
// idf.py add-dependency "esp-idf-lib/ds3231^1.1.7"
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ds3231.h"
#define SDA_GPIO GPIO_NUM_21
#define SCL_GPIO GPIO_NUM_22
void app_main(void)
{
ESP_ERROR_CHECK(i2cdev_init());
i2c_dev_t dev;
memset(&dev, 0, sizeof(i2c_dev_t));
ESP_ERROR_CHECK(ds3231_init_desc(&dev, 0, SDA_GPIO, SCL_GPIO));
while (1) {
struct tm time;
float temperature;
if (ds3231_get_time(&dev, &time) == ESP_OK && ds3231_get_temp_float(&dev, &temperature) == ESP_OK)
printf("%04d-%02d-%02d %02d:%02d:%02d, chip temp %.2f C\n",
time.tm_year + 1900, time.tm_mon + 1, time.tm_mday,
time.tm_hour, time.tm_min, time.tm_sec, temperature);
else
printf("Could not read time from RTC\n");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}ESP-IDF ships no DS3231 driver of its own, so this example uses the maintained esp-idf-lib DS3231 driver from the ESP Component Registry. Install it into your project first with idf.py add-dependency "esp-idf-lib/ds3231^1.1.7", then build as usual.
ds3231_get_time() fills a standard struct tm, and ds3231_get_temp_float() reads the DS3231's built-in die temperature sensor (used internally for its temperature-compensated crystal). To set the clock, call ds3231_set_time() once with a populated struct tm. i2cdev_init() sets up the shared I2C layer used by all esp-idf-lib drivers.
DS3231 / AT24C32 ESPHome example
Copyi2c:
sda: GPIO21
scl: GPIO22
time:
- platform: ds1307
id: rtc_time # the DS3231 is register-compatible with the ds1307 platform
text_sensor:
- platform: template
name: "DS3231 Date and Time"
lambda: |-
char buf[20];
auto now = id(rtc_time).now();
if (!now.is_valid()) return {"unknown"};
now.strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S");
return {buf};
update_interval: 1sESPHome has no dedicated DS3231 platform, but the DS3231's timekeeping registers are compatible with the ds1307 platform, which reads it fine at the same address (0x68). The custom sensor platform older examples used was removed from ESPHome in 2025 - a template text_sensor formats the time for display instead. The DS3231's extras (aging offset, alarms, die temperature) are not exposed this way.
DS3231 / AT24C32 PlatformIO example
Copy[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
adafruit/RTClib @ ^2.1.4#include <Arduino.h>
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(2023, 12, 4, 14, 30, 0)); // Set initial date/time
}
}
void loop() {
DateTime now = rtc.now();
Serial.print("Time: ");
Serial.print(now.hour());
Serial.print(":");
Serial.print(now.minute());
Serial.print(":");
Serial.println(now.second());
Serial.print("Date: ");
Serial.print(now.year());
Serial.print("/");
Serial.print(now.month());
Serial.print("/");
Serial.println(now.day());
delay(1000);
}This PlatformIO code demonstrates how to interface with the DS3231 RTC using I²C. SDA and SCL are connected to GPIO21 and GPIO22, respectively. The RTC is initialized, and if it has lost power, the date and time are set. The loop() retrieves the current time and date and prints them every second.
DS3231 / AT24C32 MicroPython example
Copyfrom machine import I2C, Pin
import time
# DS3231 I2C address
DS3231_ADDRESS = 0x68
def bcd_to_decimal(bcd):
return (bcd >> 4) * 10 + (bcd & 0x0F)
def decimal_to_bcd(decimal):
return ((decimal // 10) << 4) | (decimal % 10)
def set_time(i2c, year, month, day, hour, minute, second):
data = [decimal_to_bcd(second), decimal_to_bcd(minute), decimal_to_bcd(hour),
decimal_to_bcd(day), 0, decimal_to_bcd(month), decimal_to_bcd(year - 2000)]
i2c.writeto_mem(DS3231_ADDRESS, 0x00, bytes(data))
def get_time(i2c):
data = i2c.readfrom_mem(DS3231_ADDRESS, 0x00, 7)
second = bcd_to_decimal(data[0])
minute = bcd_to_decimal(data[1])
hour = bcd_to_decimal(data[2])
day = bcd_to_decimal(data[4])
month = bcd_to_decimal(data[5] & 0x1F)
year = bcd_to_decimal(data[6]) + 2000
return year, month, day, hour, minute, second
# Initialize I2C
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
# Set initial time
set_time(i2c, 2023, 12, 4, 14, 30, 0)
# Loop to read time
while True:
year, month, day, hour, minute, second = get_time(i2c)
print(f"Time: {hour:02}:{minute:02}:{second:02}, Date: {year:04}/{month:02}/{day:02}")
time.sleep(1)This MicroPython script interfaces with the DS3231 RTC over I²C using SDA (GPIO21) and SCL (GPIO22). The set_time() function sets the date and time on the DS3231 by writing BCD-encoded values to its memory. The get_time() function reads the current date and time from the DS3231, decodes the BCD values into integers, and returns them in a human-readable format. The main loop continuously fetches the current time and date from the DS3231 and prints them every second.
DS3231 / AT24C32 specifications
About the DS3231 / AT24C32
The DS3231 earns its reputation as the RTC to reach for when timekeeping actually matters: unlike the DS1302 and DS1307, it integrates its own temperature-compensated crystal oscillator (TCXO) instead of relying on the ambient stability of an external crystal, and it is rated to ±2ppm from 0 to 40 degC - which works out to roughly a minute of drift a year, not a month. A programmable aging-offset register lets that be trimmed further against a known-good reference if long-term precision matters enough to calibrate for it. It runs the same I2C bus and 2-wire wiring as the DS1307, so it is usually a direct swap in an existing design.
One thing worth checking before trusting a cheap DS3231 module: a lot of the low-cost breakout boards (commonly sold as “ZS-042”) were designed around a rechargeable LIR2032 backup cell and include a small trickle-charging circuit for it, but ship instead with a standard non-rechargeable CR2032 - continuously trickle-charging a non-rechargeable cell is a documented safety issue, with a real risk of the cell leaking or swelling over time. The fix that shows up across hobbyist writeups is desoldering the charging resistor (or its companion diode) near the battery holder to disable the circuit; running the module from 3.3V instead of 5V also avoids the problem, since the diode in the charging path does not forward-bias at that voltage. It is also worth knowing that counterfeit RTC chips circulate on the same cheap modules, so a board that will not hold time accurately even after this fix is worth double-checking rather than assuming the chip itself is faulty.
Between the three classic RTCs on this site, the DS3231 is the one to pick when a project genuinely needs the clock to stay accurate unattended - the PCF8563 is the better choice when battery current matters more than absolute accuracy, and the DS1307 or DS1302 mostly make sense when reproducing an existing design built around them.
DS3231 / AT24C32 troubleshooting
RTC Not Advancing Time Correctly
›
Issue: The DS3231 RTC module displays a constant time or advances time incorrectly.
Possible causes include insufficient power supply, incorrect wiring, or a defective module.
Solution: Ensure that the module is connected to a stable power source, with VCC connected to 5V and GND to ground. Verify that the SDA and SCL pins are correctly connected to the appropriate digital pins on the microcontroller. If the problem persists, consider replacing the DS3231 module, as some units, especially from unreliable sources, may be faulty.
Incorrect or Corrupted Date and Time Display
›
Issue: The DS3231 module displays incorrect or corrupted date and time information.
Possible causes include improper initialization, incorrect data retrieval methods, or communication errors.
Solution: Ensure that the RTC is properly initialized in your code, disabling write protection and setting the clock to run mode. Use reliable libraries and functions to set and retrieve time data. Verify that the communication between the microcontroller and the RTC is functioning correctly, and consider implementing error-checking mechanisms to detect and handle communication issues.
RTC Module Overheating
›
Issue: The DS3231 module becomes excessively hot during operation.
Possible causes include incorrect power connections, short circuits, or defective components.
Solution: Double-check all power connections to ensure they are correct, with VCC connected to the appropriate voltage and GND to ground. Inspect the module and wiring for any signs of short circuits or solder bridges. If the module continues to overheat, it may be defective and should be replaced.
Time Resets After Power Loss
›
Issue: The DS3231 RTC loses track of time after a power cycle.
Possible causes include a missing or depleted backup battery, or incorrect wiring of the backup power supply.
Solution: Install a backup battery (e.g., a CR2032 coin cell) to the VBAT pin to maintain timekeeping during power loss. Ensure that the battery is fresh and properly connected. Verify that the VCC pin is connected to the main power supply, and that the module is configured to switch to the backup battery when the main power is unavailable.
Where to buy the DS3231 / AT24C32

Resources
Similar sensors





