10#include "driver/i2c_master.h"
13#include "freertos/FreeRTOS.h"
14#include "freertos/task.h"
17static const char *
TAG =
"ds3231";
20#define DS3231_I2C_ADDR 0x68
23#define DS3231_REG_SECONDS 0x00
24#define DS3231_REG_MINUTES 0x01
25#define DS3231_REG_HOURS 0x02
26#define DS3231_REG_DAY 0x03
27#define DS3231_REG_DATE 0x04
28#define DS3231_REG_MONTH 0x05
29#define DS3231_REG_YEAR 0x06
32#define DS3231_REG_CONTROL 0x0E
33#define DS3231_REG_STATUS 0x0F
34#define DS3231_REG_TEMP_MSB 0x11
35#define DS3231_REG_TEMP_LSB 0x12
37#define DS3231_STATUS_OSF (1U << 7)
38#define DS3231_HOURS_12H (1U << 6)
40#define DS3231_YEAR_BASE 2000U
42static i2c_master_dev_handle_t
s_dev;
47 return (uint8_t)(((bcd >> 4) * 10U) + (bcd & 0x0FU));
52 return (uint8_t)(((bin / 10U) << 4) | (bin % 10U));
59 ESP_RETURN_ON_FALSE(data != NULL && len > 0 && len <= 7, ESP_ERR_INVALID_ARG,
60 TAG,
"bad write args");
63 for (
size_t i = 0; i < len; i++) {
71 ESP_RETURN_ON_FALSE(data != NULL && len > 0, ESP_ERR_INVALID_ARG,
TAG,
"bad read args");
77 ESP_RETURN_ON_FALSE(dt != NULL, ESP_ERR_INVALID_ARG,
TAG,
"null dt");
79 ESP_ERR_INVALID_ARG,
TAG,
"year out of range");
80 ESP_RETURN_ON_FALSE(dt->
month >= 1 && dt->
month <= 12, ESP_ERR_INVALID_ARG,
TAG,
"month");
81 ESP_RETURN_ON_FALSE(dt->
date >= 1 && dt->
date <= 31, ESP_ERR_INVALID_ARG,
TAG,
"date");
82 ESP_RETURN_ON_FALSE(dt->
weekday >= 1 && dt->
weekday <= 7, ESP_ERR_INVALID_ARG,
TAG,
"weekday");
83 ESP_RETURN_ON_FALSE(dt->
hour <= 23, ESP_ERR_INVALID_ARG,
TAG,
"hour");
84 ESP_RETURN_ON_FALSE(dt->
minute <= 59, ESP_ERR_INVALID_ARG,
TAG,
"minute");
85 ESP_RETURN_ON_FALSE(dt->
second <= 59, ESP_ERR_INVALID_ARG,
TAG,
"second");
92 esp_err_t err = ESP_OK;
103 for (attempt = 1; attempt <= 3; attempt++) {
108 ESP_LOGW(
TAG,
"probe 0x%02X attempt %d/3 failed: %s",
110 vTaskDelay(pdMS_TO_TICKS(20));
114 ESP_LOGE(
TAG,
"DS3231 not responding at 0x%02X (%s). Check wiring/power/pull-ups",
116 (void)i2c_master_bus_rm_device(
s_dev);
122 ESP_LOGI(
TAG,
"DS3231 at 0x%02X, status=0x%02X%s",
132 ESP_RETURN_ON_FALSE(
s_initialized, ESP_ERR_INVALID_STATE,
TAG,
"not initialized");
133 ESP_RETURN_ON_FALSE(dt != NULL, ESP_ERR_INVALID_ARG,
TAG,
"null dt");
136 TAG,
"read time failed");
144 bool pm = (raw[2] & (1U << 5)) != 0;
146 dt->
hour = pm ? 12 : 0;
148 dt->
hour = (uint8_t)(pm ? hour12 + 12 : hour12);
166 ESP_RETURN_ON_FALSE(
s_initialized, ESP_ERR_INVALID_STATE,
TAG,
"not initialized");
178 TAG,
"write time failed");
188 ESP_RETURN_ON_FALSE(
s_initialized, ESP_ERR_INVALID_STATE,
TAG,
"not initialized");
189 ESP_RETURN_ON_FALSE(temp_c != NULL, ESP_ERR_INVALID_ARG,
TAG,
"null temp");
192 TAG,
"read temp failed");
195 int8_t whole = (int8_t)raw[0];
196 float frac = (float)((raw[1] >> 6) & 0x03U) * 0.25f;
197 *temp_c = (float)whole + frac;
205 ESP_RETURN_ON_FALSE(
s_initialized, ESP_ERR_INVALID_STATE,
TAG,
"not initialized");
206 ESP_RETURN_ON_FALSE(stopped != NULL, ESP_ERR_INVALID_ARG,
TAG,
"null stopped");
209 TAG,
"read status failed");
218 ESP_RETURN_ON_FALSE(
s_initialized, ESP_ERR_INVALID_STATE,
TAG,
"not initialized");
221 TAG,
"read status failed");
esp_err_t ds3231_set_time(const ds3231_datetime_t *dt)
Записать дату и время в DS3231 (24-часовой режим).
#define DS3231_I2C_ADDR
7-битный адрес DS3231 на шине
esp_err_t ds3231_init(void)
Добавляет DS3231 на общую I2C-шину и проверяет доступность.
static i2c_master_dev_handle_t s_dev
esp_err_t ds3231_get_temperature(float *temp_c)
Прочитать температуру с встроенного датчика DS3231.
static uint8_t bin_to_bcd(uint8_t bin)
static esp_err_t ds3231_read_regs(uint8_t reg, uint8_t *data, size_t len)
static bool s_initialized
esp_err_t ds3231_get_time(ds3231_datetime_t *dt)
Прочитать текущие дату и время из DS3231.
static esp_err_t ds3231_write_regs(uint8_t reg, const uint8_t *data, size_t len)
static esp_err_t ds3231_validate_datetime(const ds3231_datetime_t *dt)
esp_err_t ds3231_is_oscillator_stopped(bool *stopped)
Проверить, был ли остановлен осциллятор (потеря питания / батареи).
static uint8_t bcd_to_bin(uint8_t bcd)
#define DS3231_REG_TEMP_MSB
#define DS3231_REG_SECONDS
esp_err_t ds3231_clear_osf(void)
Сбросить флаг OSF в Status-регистре.
#define DS3231_STATUS_OSF
#define DS3231_REG_STATUS
Драйвер часов реального времени Maxim DS3231 (I2C).
esp_err_t i2c_bus_init(void)
Создаёт master-шину I2C (идемпотентно).
esp_err_t i2c_bus_add_device(uint8_t addr7, i2c_master_dev_handle_t *dev)
Добавить устройство с 7-битным адресом на общую шину.
Общая I2C-шина master (I2C_NUM_0) для всех периферийных устройств.
#define I2C_BUS_TIMEOUT_MS