All parts / DS3231
DS3231 register map
Extremely accurate I2C real-time clock with integrated TCXO and crystal — Analog Devices
19 registers
I2C
I²C 0x68
8-bit reg addresses
50% bit coverage
not yet human-verified
I²C address conflict. On its default address(es) this part collides with
DS1307 (0x68);
MPU6050 (0x68);
PCA9685 (0x68). You cannot put them on the same bus without changing a strap pin, using an I²C multiplexer, or moving one to a second bus.
See the full address map.
Get it as a C header
pip install regforge
regforge gen DS3231 --out ./src --driver --tests
Writes ds3231_regs.h with every address, mask and shift below, a bus-agnostic driver skeleton, and a file of compile-time assertions that make your compiler check the bit arithmetic. No API key needed — this part ships inside the package.
Not yet human-verified. Transcribed and mechanically validated — no overlapping fields, no out-of-range bits, reset values consistent with their fields — but not yet checked line-by-line against the datasheet.
Verifying it is a useful half hour.
Registers
| Addr | Register | Access | Width | Reset | Description |
| 0x00 | SECONDS | RW | 8 | — | Seconds, BCD, 00-59 |
| 0x01 | MINUTES | RW | 8 | — | Minutes, BCD, 00-59 |
| 0x02 | HOURS | RW | 8 | — | Hours, BCD. Format depends on the 12/24 bit. |
| 0x03 | DAY | RW | 8 | — | Day of week, 1-7. Defined by the user and incremented at midnight. |
| 0x04 | DATE | RW | 8 | — | Day of month, BCD, 01-31 |
| 0x05 | MONTH_CENTURY | RW | 8 | — | Month in BCD, plus the century flag |
| 0x06 | YEAR | RW | 8 | — | Year within the century, BCD, 00-99 |
| 0x07 | ALARM1_SECONDS | RW | 8 | — | Alarm 1 seconds, BCD, with the A1M1 mask in bit 7 |
| 0x08 | ALARM1_MINUTES | RW | 8 | — | Alarm 1 minutes, BCD, with the A1M2 mask in bit 7 |
| 0x09 | ALARM1_HOURS | RW | 8 | — | Alarm 1 hours, BCD, with the A1M3 mask in bit 7 |
| 0x0A | ALARM1_DAY_DATE | RW | 8 | — | Alarm 1 day or date, selected by DY/DT |
| 0x0B | ALARM2_MINUTES | RW | 8 | — | Alarm 2 minutes, BCD, with the A2M2 mask in bit 7 |
| 0x0C | ALARM2_HOURS | RW | 8 | — | Alarm 2 hours, BCD, with the A2M3 mask in bit 7 |
| 0x0D | ALARM2_DAY_DATE | RW | 8 | — | Alarm 2 day or date, selected by DY/DT |
| 0x0E | CONTROL | RW | 8 | 0x1C | Oscillator, square wave and alarm interrupt control |
| 0x0F | STATUS | RW | 8 | — | Oscillator stop flag, 32 kHz output enable and alarm flags |
| 0x10 | AGING_OFFSET | RW | 8 | — | Aging offset, two's complement, applied to the oscillator capacitance |
| 0x11 | TEMP_MSB | RO | 8 | — | Temperature, integer part, two's complement |
| 0x12 | TEMP_LSB | RO | 8 | — | Temperature, fractional part in bits [7:6], 0.25 C per LSB |
Bit layouts
Drawn MSB-first, the way the datasheet draws them. [7:5] means shift 5, width 3, mask 0xE0 — this is the notation that costs people a day when they read it backwards.
SECONDS @ 0x00 — 2 fields
—7
SECONDS_10[6:4]
SECONDS_1[3:0]
| Bits | Field | Access | Mask | Reset | Description |
| [6:4] | SECONDS_10 | RW | 0x70 | — | Tens of seconds, 0-5 |
| [3:0] | SECONDS_1 | RW | 0x0F | — | Units of seconds, 0-9 |
MINUTES @ 0x01 — 2 fields
—7
MINUTES_10[6:4]
MINUTES_1[3:0]
| Bits | Field | Access | Mask | Reset | Description |
| [6:4] | MINUTES_10 | RW | 0x70 | — | Tens of minutes, 0-5 |
| [3:0] | MINUTES_1 | RW | 0x0F | — | Units of minutes, 0-9 |
HOURS @ 0x02 — 4 fields
—7
MODE_12_24[6]
AM_PM_HOUR_20[5]
HOURS_10[4]
HOURS_1[3:0]
| Bits | Field | Access | Mask | Reset | Description |
| [6] | MODE_12_24 | RW | 0x40 | — | 0 = 24-hour mode, 1 = 12-hour mode |
| [5] | AM_PM_HOUR_20 | RW | 0x20 | — | In 12-hour mode: 0 = AM, 1 = PM. In 24-hour mode: the 20-hour bit. |
| [4] | HOURS_10 | RW | 0x10 | — | The 10-hour bit |
| [3:0] | HOURS_1 | RW | 0x0F | — | Units of hours, 0-9 |
HOURS.MODE_12_24 values
| Value | Name | Meaning |
| 0x00 | MODE_24H | 24-hour format |
| 0x01 | MODE_12H | 12-hour format, bit 5 is AM/PM |
DAY @ 0x03 — 1 fields
| Bits | Field | Access | Mask | Reset | Description |
| [2:0] | DAY | RW | 0x07 | — | Day of week, 1-7 |
DATE @ 0x04 — 2 fields
—7
—6
DATE_10[5:4]
DATE_1[3:0]
| Bits | Field | Access | Mask | Reset | Description |
| [5:4] | DATE_10 | RW | 0x30 | — | Tens of the date, 0-3 |
| [3:0] | DATE_1 | RW | 0x0F | — | Units of the date, 0-9 |
MONTH_CENTURY @ 0x05 — 3 fields
CENTURY[7]
—6
—5
MONTH_10[4]
MONTH_1[3:0]
| Bits | Field | Access | Mask | Reset | Description |
| [7] | CENTURY | RW | 0x80 | — | Toggles when the year counter overflows from 99 to 00 |
| [4] | MONTH_10 | RW | 0x10 | — | Tens of the month |
| [3:0] | MONTH_1 | RW | 0x0F | — | Units of the month, 0-9 |
YEAR @ 0x06 — 2 fields
| Bits | Field | Access | Mask | Reset | Description |
| [7:4] | YEAR_10 | RW | 0xF0 | — | Tens of the year |
| [3:0] | YEAR_1 | RW | 0x0F | — | Units of the year |
ALARM1_SECONDS @ 0x07 — 1 fields
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A1M1 | RW | 0x80 | — | Alarm 1 mask bit 1 |
ALARM1_MINUTES @ 0x08 — 1 fields
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A1M2 | RW | 0x80 | — | Alarm 1 mask bit 2 |
ALARM1_HOURS @ 0x09 — 1 fields
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A1M3 | RW | 0x80 | — | Alarm 1 mask bit 3 |
ALARM1_DAY_DATE @ 0x0A — 2 fields
A1M4[7]
DY_DT[6]
—5
—4
—3
—2
—1
—0
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A1M4 | RW | 0x80 | — | Alarm 1 mask bit 4 |
| [6] | DY_DT | RW | 0x40 | — | 0 = match the date, 1 = match the day of week |
ALARM2_MINUTES @ 0x0B — 1 fields
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A2M2 | RW | 0x80 | — | Alarm 2 mask bit 2 |
ALARM2_HOURS @ 0x0C — 1 fields
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A2M3 | RW | 0x80 | — | Alarm 2 mask bit 3 |
ALARM2_DAY_DATE @ 0x0D — 2 fields
A2M4[7]
DY_DT[6]
—5
—4
—3
—2
—1
—0
| Bits | Field | Access | Mask | Reset | Description |
| [7] | A2M4 | RW | 0x80 | — | Alarm 2 mask bit 4 |
| [6] | DY_DT | RW | 0x40 | — | 0 = match the date, 1 = match the day of week |
CONTROL @ 0x0E — 8 fields
EOSC[7]
BBSQW[6]
CONV[5]
RS2[4]
RS1[3]
INTCN[2]
A2IE[1]
A1IE[0]
| Bits | Field | Access | Mask | Reset | Description |
| [7] | EOSC | RW | 0x80 | 0x00 | Enable oscillator, active low. 0 = oscillator runs on battery. |
| [6] | BBSQW | RW | 0x40 | 0x00 | Battery-backed square wave enable |
| [5] | CONV | W1P | 0x20 | 0x00 | Force a temperature conversion; self-clearing |
| [4] | RS2 | RW | 0x10 | 0x01 | Square wave rate select, high bit |
| [3] | RS1 | RW | 0x08 | 0x01 | Square wave rate select, low bit |
| [2] | INTCN | RW | 0x04 | 0x01 | Interrupt control. 1 = INT/SQW outputs alarm interrupts. |
| [1] | A2IE | RW | 0x02 | 0x00 | Alarm 2 interrupt enable |
| [0] | A1IE | RW | 0x01 | 0x00 | Alarm 1 interrupt enable |
STATUS @ 0x0F — 5 fields
OSF[7]
—6
—5
—4
EN32KHZ[3]
BSY[2]
A2F[1]
A1F[0]
| Bits | Field | Access | Mask | Reset | Description |
| [7] | OSF | RW1C | 0x80 | — | Oscillator stop flag: the timekeeping data may be invalid |
| [3] | EN32KHZ | RW | 0x08 | 0x01 | Enable the 32 kHz output |
| [2] | BSY | RO | 0x04 | — | Busy executing a temperature conversion |
| [1] | A2F | RW1C | 0x02 | — | Alarm 2 flag; write 0 to clear |
| [0] | A1F | RW1C | 0x01 | — | Alarm 1 flag; write 0 to clear |
TEMP_LSB @ 0x12 — 1 fields
TEMP_FRACTION[7:6]
—5
—4
—3
—2
—1
—0
| Bits | Field | Access | Mask | Reset | Description |
| [7:6] | TEMP_FRACTION | RO | 0xC0 | — | Fractional temperature, 0.25 C per count |
Generated C header
What regforge gen DS3231 writes for CONTROL:
/* ------------------------------------------------------------------------ */
/* CONTROL @ 0x0Eu rw 8-bit reset 0x1Cu */
/* Oscillator, square wave and alarm interrupt control */
/* ------------------------------------------------------------------------ */
#define DS3231_CONTROL 0x0Eu
#define DS3231_CONTROL_WIDTH 8u
#define DS3231_CONTROL_RESET 0x1Cu
/* EOSC bits [7] rw reset 0x00u -- Enable oscillator, active low. 0 = oscillator runs on battery. */
#define DS3231_CONTROL_EOSC_SHIFT 7u
#define DS3231_CONTROL_EOSC_WIDTH 1u
#define DS3231_CONTROL_EOSC_MASK 0x80u
#define DS3231_CONTROL_EOSC_GET(reg) (((uint8_t)(reg) & 0x80u) >> 7u)
#define DS3231_CONTROL_EOSC_SET(reg, val) (((uint8_t)(reg) & (uint8_t)~0x80u) | (((uint8_t)(val) << 7u) & 0x80u))
/* BBSQW bits [6] rw reset 0x00u -- Battery-backed square wave enable */
#define DS3231_CONTROL_BBSQW_SHIFT 6u
#define DS3231_CONTROL_BBSQW_WIDTH 1u
#define DS3231_CONTROL_BBSQW_MASK 0x40u
#define DS3231_CONTROL_BBSQW_GET(reg) (((uint8_t)(reg) & 0x40u) >> 6u)
#define DS3231_CONTROL_BBSQW_SET(reg, val) (((uint8_t)(reg) & (uint8_t)~0x40u) | (((uint8_t)(val) << 6u) & 0x40u))
/* CONV bits [5] w1p reset 0x00u -- Force a temperature conversion; self-clearing */
#define DS3231_CONTROL_CONV_SHIFT 5u
#define DS3231_CONTROL_CONV_WIDTH 1u
#define DS3231_CONTROL_CONV_MASK 0x20u
#define DS3231_CONTROL_CONV_GET(reg) (((uint8_t)(reg) & 0x20u) >> 5u)
#define DS3231_CONTROL_CONV_SET(reg, val) (((uint8_t)(reg) & (uint8_t)~0x20u) | (((uint8_t)(val) << 5u) & 0x20u))
/* RS2 bits [4] rw reset 0x01u -- Square wave rate select, high bit */
#define DS3231_CONTROL_RS2_SHIFT 4u
#define DS3231_CONTROL_RS2_WIDTH 1u
#define DS3231_CONTROL_RS2_MASK 0x10u
#define DS3231_CONTROL_RS2_GET(reg) (((uint8_t)(reg) & 0x10u) >> 4u)
#define DS3231_CONTROL_RS2_SET(reg, val) (((uint8_t)(reg) & (uint8_t)~0x10u) | (((uint8_t)(val) << 4u) & 0x10u))
/* RS1 bits [3] rw reset 0x01u -- Square wave rate select, low bit */
#define DS3231_CONTROL_RS1_SHIFT 3u
#define DS3231_CONTROL_RS1_WIDTH 1u
#define DS3231_CONTROL_RS1_MASK 0x08u
#define DS3231_CONTROL_RS1_GET(reg) (((uint8_t)(reg) & 0x08u) >> 3u)
#define DS3231_CONTROL_RS1_SET(reg, val) (((uint8_t)(reg) & (uint8_t)~0x08u) | (((uint8_t)(val) << 3u) & 0x08u))
Compared with
Related parts
Source
Transcribed from Maxim/ADI DS3231 datasheet (hand-transcribed) (hand-transcribed). Hand-authored seed entry, not machine-extracted. Timekeeping registers carry no reset value because the datasheet states none -- they hold whatever the backup supply preserved. Time and date fields are BCD. Check against the DS3231 datasheet before trusting it, then mark it verified.
Raw JSON · Report an error