В данной статье мы научимся взаимодействовать с модулем RTC DS3231, используя ESP32 и ESP-IDF. Мы кратко рассмотрим описание модуля DS3231, его подключение к плате ESP32, а также настройку проекта в VS Code с расширением ESP-IDF для получения текущей даты/времени и отображения их на консоли.

Аналогичный проект на нашем сайте вы также можете посмотреть на основе модуля DS1307.
Ранее на нашем сайте мы рассматривали и другие проекты с использованием модуля DS3231:
- часы реального времени на ESP32 и модуле DS3231;
- цифровые часы на микроконтроллере PIC и RTC модуле DS3231;
- подключение модуля часов реального времени DS3231 к плате STM32F103C8 (Blue Pill);
- подключение модуля часов реального времени (RTC) DS3231 к NodeMCU ESP8266.
Прецизионный модуль RTC DS3231
Модуль DS3231 RTC широко используется для отслеживания текущей даты и времени. Он применяется в электронных проектах для измерения времени, регистрации данных, создания часов, таймеров и т. д. Этот модуль работает на микросхеме DS3231S RTC и также содержит EEPRROM AT24C3 для точного измерения времени. Модуль состоит из интегрированного кварцевого генератора с температурной компенсацией и кварцевого резонатора, что делает его чрезвычайно точным модулем RTC. Кроме того, благодаря наличию кварцевого резонатора точность времени сохраняется в течение длительного времени.
На обратной стороне модуля RTC расположен держатель для 20-миллиметровой литиевой батарейки-таблетки 3 В, в которую устанавливается батарейка CR2032. Эта батарейка крайне важна для отслеживания времени и обеспечения его точности в случае отключения основного питания. Таким образом, батарейка CR2032 выступает в качестве резервного источника питания на случай потери основного источника энергии.
На приведенной ниже схеме показаны лицевая и обратная стороны модуля DS3231 RTC. Обратите внимание, что на лицевой стороне расположены микросхема DS3231 RTC и EEPROM 24C32, а на обратной стороне — держатель батареи CR2032 и батарейка-таблетка соответственно.
Распиновка модуля RTC DS3231
На приведенной ниже схеме показана распиновка модуля RTC DS3231.
Как видно на приведенном рисунке, модуль DS3231 имеет в общей сложности десять контактов, но для доступа к текущему времени с помощью одного модуля нам требуются только контакты связи I2C (SCL и SDA) и контакты питания (VCC и GND). Контакты I2C и питания на другой стороне модуля предназначены для подключения к другому модулю (последовательное соединение).
| 33K | Этот контакт выдает компенсированную температуру и точный опорный тактовый сигнал. |
| SQW | Этот вывод генерирует прямоугольные импульсы различной частоты, например, 1 Гц, 4 кГц, 8 кГц или 32 кГц. |
| SCL | Контакт передачи синхросигнала в интерфейсе I2C |
| SDA | Контакт передачи данных в интерфейсе I2C |
| VCC | Это контакт питания, который подключается к Vin (5 В) или 3,3 В микроконтроллера ESP32. |
| GND | Общий провод (земля) |
Как видим, распиновка у модуля достаточно понятная.
Подключение модуля DS3231 к ESP32
Для подключения модуля DS3231 к плате ESP32 нам понадобятся следующие компоненты:
- Плата ESP32.
- Модуль DS3231.
- Соединительные провода.
- Макетная плата.
Подключение модуля DS3231 к плате ESP32 довольно простое, так как оно включает в себя лишь соединение 4 контактов (GND, VCC, SDA и SCL) с ESP32. Необходимо соединить вывод VCC с контактом Vin, заземление с общим заземлением, контакт SCL датчика с контактом SCL платы ESP32, а контакт SDA датчика с контактом SDA платы ESP32. Для подключения модуля датчика будут использоваться стандартные контакты I2C платы ESP32.
В ESP32 по умолчанию для вывода SDA используется GPIO21, а для SCL — GPIO22.
Соединения между устройствами указаны в таблице ниже:
| Модуль DS3231 | ESP32 |
| GND | GND |
| VCC | 3.3V |
| SDA | GPIO21(I2C SDA) |
| SCL | GPIO22 (I2C SCL) |

Часы реального времени на базе ESP32 с использованием модуля DS3231 и ESP-IDF
Мы создадим проект в VS Code с расширением ESP-IDF. Код будет выводить текущую дату/время и внутреннюю температуру чипа в терминал ESP-IDF, используя библиотеку I2C-устройств esp_idf_lib_helpers и ds3231.h. Мы будем использовать драйвер ds3231, написанный UncleRus.
Создание примера проекта
Откройте VS Code и перейдите в меню View > Command Palette («Вид» > «Палитра команд»). Введите в строке поиска ESP-IDF: New Project и нажмите Enter.
Укажите название проекта и каталог, а также плату и целевое устройство ESP-IDF. Мы назвали наш проект «DS3231_ESP32». Для платы ESP-IDF мы выбрали опцию custom board ("пользовательская плата"). Для целевого устройства ESP-IDF мы выбрали модуль ESP32. Нажмите кнопку ‘Choose Template’ ("Выбрать шаблон"), чтобы продолжить.
В разделе «Расширение» выберите опцию ESP-IDF:
На вкладке get-started («Начало работы») мы щелкнем по пункту «sample_project». Затем нажмем ‘Create project using template sample_project’) («Создать проект, используя шаблон sample_project»).
Вы получите уведомление о создании проекта. Чтобы открыть проект в новом окне, нажмите «Да».
Это откроет проект, который мы создали на вкладке «Проводник». Внутри папки проекта находится несколько папок. Это справедливо для каждого проекта, который вы будете создавать с помощью ESP-IDF Explorer.
Для начала добавим необходимые заголовочные файлы для библиотек, требуемых для этого проекта. Создайте новую папку с названием «components» и добавьте в неё следующие три подпапки:
- esp_idf_lib_helpers
- i2cdev
- ds3231
Добавьте папки ds3231, esp_idf_lib_helpers и i2cdev в папку 'components', скопировав их по указанной ниже ссылке :

Код ESP32 для отображения текущего времени и даты с DS3231
Теперь перейдите к файлу main.c. В папке main находится исходный код, то есть файл main.c будет находиться здесь. Перейдите в папку main > main.c и откройте его. Скопируйте приведенный ниже код из этого файла и сохраните его.
Это пример скетча для драйвера DS3231. Он непрерывно выводит текущую дату и время, а также внутреннюю температуру микросхемы в терминале ESP-IDF.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#include <stdio.h> #include <freertos/FreeRTOS.h> #include <freertos/task.h> #include <ds3231.h> #include <string.h> void ds3231_test(void *pvParameters) { i2c_dev_t dev; memset(&dev, 0, sizeof(i2c_dev_t)); ESP_ERROR_CHECK(ds3231_init_desc(&dev, 0, 21, 22)); struct tm time = { .tm_year = 122, // (2022 - 1900) .tm_mon = 11, // 0-based .tm_mday = 15, .tm_hour = 0, .tm_min = 50, .tm_sec = 10 }; ESP_ERROR_CHECK(ds3231_set_time(&dev, &time)); while (1) { float temp; vTaskDelay(pdMS_TO_TICKS(250)); if (ds3231_get_temp_float(&dev, &temp) != ESP_OK) { printf("Could not get temperature\n"); continue; } if (ds3231_get_time(&dev, &time) != ESP_OK) { printf("Could not get time\n"); continue; } /* float is used in printf(). you need non-default configuration in * sdkconfig for ESP8266, which is enabled by default for this * example. see sdkconfig.defaults.esp8266 */ printf("%04d-%02d-%02d %02d:%02d:%02d, %.2f deg Cel\n", time.tm_year + 1900 /*Add 1900 for better readability*/, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, temp); } } void app_main() { ESP_ERROR_CHECK(i2cdev_init()); xTaskCreate(ds3231_test, "ds3231_test", configMINIMAL_STACK_SIZE * 3, NULL, 5, NULL); } |
Как работает код?
Для начала мы подключим необходимые библиотеки для этого проекта. Это включает библиотеку ds3231 для доступа к API для настройки и получения текущей даты/времени, а также библиотеки freertos для создания задачи.
|
1 2 3 4 5 |
#include <stdio.h> #include <freertos/FreeRTOS.h> #include <freertos/task.h> #include <ds3231.h> #include <string.h> |
ds3231_test()
Внутри функции ds3231_test() мы сначала создаём экземпляр структуры i2c_dev_t, которая используется для настройки и инициализации модуля RTC. После этого мы инициализируем все члены этой структуры нулями с помощью функции memset.
|
1 2 |
i2c_dev_t dev; memset(&dev, 0, sizeof(i2c_dev_t)); |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * I2C device descriptor */ typedef struct { i2c_port_t port; //!< I2C port number i2c_config_t cfg; //!< I2C driver configuration uint8_t addr; //!< Unshifted address SemaphoreHandle_t mutex; //!< Device mutex uint32_t timeout_ticks; /*!< HW I2C bus timeout (stretch time), in ticks. 80MHz APB clock ticks for ESP-IDF, CPU ticks for ESP8266. When this value is 0, I2CDEV_MAX_STRETCH_TIME will be used */ } i2c_dev_t; |
Далее функция ds3231_init_desc() инициализирует дескриптор устройства ds3231, передавая ему структуру dev, порт I2C, контакт ESP32 SDA и контакт ESP32 SCL соответственно.
|
1 |
ESP_ERROR_CHECK(ds3231_init_desc(&dev, 0, 21, 22)); |
Далее мы определяем параметры структуры tm, которую мы называем 'time'. Внутри неё мы указываем текущий год, месяц, дату, час, минуту и секунду. После этого мы вызываем функцию ds3231_set_time() для инициализации даты и времени в соответствии с определением в структуре time. Эта функция, по сути, устанавливает время в RTC (часы реального времени).
|
1 2 3 4 5 6 7 8 9 |
struct tm time = { .tm_year = 122, // (2022 - 1900) .tm_mon = 11, // 0-based .tm_mday = 15, .tm_hour = 0, .tm_min = 50, .tm_sec = 10 }; ESP_ERROR_CHECK(ds3231_set_time(&dev, &time)); |
Внутри цикла while мы получаем доступ к текущей дате и времени с помощью функции ds3231_get_time() и к внутренней температуре чипа с помощью функции ds3231_get_temp_float(). Каждые 0,25 секунды мы выводим внутреннюю температуру чипа и текущую дату и время на терминал ESP-IDF, обращаясь к каждому члену структуры time.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
while (1) { float temp; vTaskDelay(pdMS_TO_TICKS(250)); if (ds3231_get_temp_float(&dev, &temp) != ESP_OK) { printf("Could not get temperature\n"); continue; } if (ds3231_get_time(&dev, &time) != ESP_OK) { printf("Could not get time\n"); continue; } printf("%04d-%02d-%02d %02d:%02d:%02d, %.2f deg Cel\n", time.tm_year + 1900 /*Add 1900 for better readability*/, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, temp); } |
app_main()
Внутри функции app_main() мы сначала инициализируем устройство I2C, вызвав функцию i2cdev_init(). Затем мы создадим задачу DS3231 с помощью функции xTaskCreate().
|
1 2 3 4 5 |
void app_main() { ESP_ERROR_CHECK(i2cdev_init()); xTaskCreate(ds3231_test, "ds3231_test", configMINIMAL_STACK_SIZE * 3, NULL, 5, NULL); } |
Компиляция скетча
Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.
|
1 |
idf.py -p COMX flash monitor |
После успешной прошивки кода вы сможете просмотреть текущую дату и время, а также внутреннюю температуру чипа на консоли.
12 просмотров









