Андрей Смирнов
Время чтения: ~17 мин.
Просмотров: 7

Часы реального времени на RTC модулях Ардуино DS1302, DS1307, DS3231

Для подключения RTC часов реального времени DS1302, DS1307, DS3231, была разработана универсальная библиотека.aadd7388f5f609bdcaf02bcecac0f305.jpg

Скачать библиотеку можно по ссылке : Универсальная библиотека для RTC DS1302, DS1307, DS3231 к Arduino

Подключение:

Подключение DS1307 к Arduino:

RTC DS1307 Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Подключение DS1302 к Arduino:

RTC DS1302 Arduino UNO
GND GND
VCC +5V
RST 10 (Можно изменить на другие в скетче)
CLK 13 (Можно изменить на другие в скетче)
DAT 12 (Можно изменить на другие в скетче)

Подключение DS3231 к Arduino:

RTC DS3231 Arduino UNO
GND GND
VCC +5V
SDA A4
SCL

Программа:

В зависимости от того какой модуль Вы подключаете, необходимо в программе указать

Для DS1307:

Для DS1302:

Для DS3231:

Пример установки текущего времени в RTC модуль (DS1307):

Пример считывания текущего времени с RTC модуля (DS1307) и вывод в «Последовательный порт» :

Преимущества библиотеки:

— библиотека имеет внутренние функции аппаратной обработки протоколов передачи данных I2C и SPI, а следовательно не требует подключения дополнительных библиотек, но и не конфликтует с ними, если таковые всё же подключены.

— библиотека имеет внутренние функции программой обработки протокола передачи данных 3-Wire

— для инициализации модуля необходимо вызвать функцию begin с названием модуля.

— подключение модулей осуществляется к аппаратным выводам arduino используемой шины (за исключением 3-Wire)

— простота установки и чтения времени функциями settime и gettime

функция settime может устанавливать дату и время, как полностью, так и частично (например только минуты, или только день, и т.д.)

функция gettime работает как функция date в php, возвращая строку со временем, но если её вызвать без параметра, то функция ничего не вернёт, а время можно прочитать из переменных в виде чисел.

— библиотека расширяемая, то есть для того, чтоб она работала с новым модулем, нужно указать параметры этого модуля в уже существующих массивах файла RTC.h (тип шины, частота шины в кГц, режимы работы, адреса регистров и т.д.), как всё это сделать, описано в файле extension.txt

Таким образом добавив новый модуль в библиотеку, мы лишь увеличим область занимаемой динамической памяти на ~ 36 байт, при этом не затронув область памяти программ.

— при вызове функции begin, библиотека читает флаги регистров модуля и при необходимости устанавливает или сбрасывает их так, чтоб модуль мог работать от аккумуляторной батареи, а на программируемом выводе меандра (если таковой у модуля есть) установилась частота 1Гц, тогда этот вывод можно использовать в качестве внешнего посекундного прерывания.

— при работе с модулем DS1302 не нужны никакие резисторы на выводе GND (которые нужны для его работы с другими библиотеками этого модуля), это достигнуто тем, что для шины 3-Wire указана конкретная частота 10кГц, не зависимо от частоты CPU arduino.

— в библиотеке реализована еще одна не обязательная функция period, принимающая в качестве единственного аргумента — количество минут (от 1 до 255)

если в течении указанного времени была вызвана функция gettime несколько раз, то запрос к модулю по шине будет отправлено только в первый раз, а ответом на все остальные запросы будет сумма времени последнего ответа модуля и времени прошедшего с этого ответа.

Функцию period достаточно вызвать один раз.

Подробное описание:

Во многих проектах Ардуино требуется отслеживать и фиксировать время наступления тех или иных событий. Модуль часов реального времени, оснащенный дополнительной батарей, позволяет хранить текущую дату, не завися от наличия питания на самом устройстве. В этой статье мы поговорим о наиболее часто встречающихся модулях RTC DS1307, DS1302, DS3231, которые можно использовать с платой Arduino.

Модули часов реального времени в проектах Arduino

Модуль часов представляет собой небольшую плату, содержащей, как правило, одну из микросхем DS1307, DS1302, DS3231.Кроме этого, на плате практически можно найти механизм установки батарейки питания. Такие платы часто  применяется для учета времени, даты, дня недели и других хронометрических параметров. Модули работают от автономного питания – батареек, аккумуляторов, и продолжают проводить отсчет, даже если на Ардуино отключилось питание. Наиболее распространенными моделями часов являются DS1302, DS1307, DS3231. Они основаны на подключаемом к Arduino модуле RTC (часы реального времени).

Часы ведут отсчет в единицах, которые удобны обычному человеку – минуты, часы, дни недели и другие, в отличие от обычных счетчиков и тактовых генераторов, которые считывают «тики». В Ардуино имеется специальная функция millis(), которая также может считывать различные временные интервалы. Но основным недостатком этой функции является сбрасывание в ноль при включении таймера. С ее помощью можно считать только время, установить дату или день недели невозможно. Для решения этой проблемы и используются модули часов реального времени.

Электронная схема включает в себя микросхему, источник питания, кварцевый резонатор и резисторы. Кварцевый резонатор работает на частоте 32768 Гц, которая является удобной для обычного двоичного счетчика. В схеме DS3231 имеется встроенный кварц и термостабилизация, которые позволяют получить значения высокой точности.

Сравнение популярных модулей RTC DS1302, DS1307, DS3231

В этой таблице мы привели список наиболее популярных модулей и их основные характеристики.

Название Частота Точность Поддерживаемые протоколы
DS1307 1 Гц, 4.096 кГц, 8.192 кГц, 32.768 кГц Зависит от кварца – обычно значение достигает 2,5 секунды в сутки, добиться точности выше 1 секунды в сутки невозможно. Также точность зависит от температуры. I2C
DS1302 32.768 кГц 5 секунд в сутки I2C, SPI
DS3231 Два выхода – первый на 32.768 кГц, второй – программируемый от 1 Гц до 8.192 кГц ±2 ppm при температурах от 0С до 40С.

±3,5 ppm при температурах от -40С до 85С.

Точность измерения температуры – ±3С

I2C

Модуль DS1307

DS1307 – это модуль, который используется для отсчета времени. Он собран на основе микросхемы DS1307ZN, питание поступает от литиевой батарейки для реализации автономной работы в течение длительного промежутка времени. Батарея на плате крепится на обратной стороне. На модуле имеется микросхема AT24C32 – это энергонезависимая память EEPROM на 32 Кбайт. Обе микросхемы связаны между собой шиной I2C. DS1307 обладает низким энергопотреблением и содержит часы и календарь по 2100 год.

Модуль обладает следующими параметрами:

  • Питание – 5В;
  • Диапазон рабочих температур от -40С до 85С;
  • 56 байт памяти;
  • Литиевая батарейка LIR2032;
  • Реализует 12-ти и 24-х часовые режимы;
  • Поддержка интерфейса I2C.

Модуль оправдано использовать в случаях, когда данные считываются довольно редко, с интервалом в неделю и более. Это позволяет экономить на питании, так как при бесперебойном использовании придется больше тратить напряжения, даже при наличии батарейки. Наличие памяти позволяет регистрировать различные параметры (например, измерение температуры) и считывать полученную информацию из модуля.

Взаимодействие с другими устройствами и обмен с ними информацией производится с помощью интерфейса I2C с контактов SCL и SDA. В схеме установлены резисторы, которые позволяют обеспечивать необходимый уровень сигнала. Также на плате имеется специальное место для крепления датчика температуры DS18B20.Контакты распределены в 2 группы, шаг 2,54 мм. В первой группе контактов находятся следующие выводы:

  • DS – вывод для датчика DS18B20;
  • SCL – линия тактирования;
  • SDA – линия данных;
  • VCC – 5В;
  • GND.

Во второй группе контактов находятся:

  • SQ – 1 МГц;
  • DS ;
  • SCL;
  • SDA;
  • VCC;
  • GND;
  • BAT – вход для литиевой батареи.

podklyuchenie-300x300.jpg

Для подключения к плате Ардуино нужны сама плата (в данном случае рассматривается Arduino Uno), модуль часов реального времени RTC DS1307, провода и USB кабель.

Чтобы подключить контроллер к Ардуино, используются 4 пина – VCC, земля, SCL, SDA.. VCC с часов подключается к 5В на Ардуино, земля с часов – к земле с Ардуино, SDA – А4, SCL – А5.

budilnik1-300x147.png

Для начала работы с модулем часов нужно установить библиотеки DS1307RTC, TimeLib и Wire. Можно использовать для работы и RTCLib.

Проверка RTC модуля

При запуске первого кода программа будет считывать данные с модуля раз в секунду. Сначала можно посмотреть, как поведет себя программа, если достать из модуля батарейку и заменить на другую, пока плата Ардуино не присоединена к компьютеру. Нужно подождать несколько секунд и вытащить батарею, в итоге часы перезагрузятся. Затем нужно выбрать пример в меню Examples→RTClib→ds1307. Важно правильно поставить скорость передачи на 57600 bps.

При открытии окна серийного монитора должны появиться следующие строки:

Будет показывать время 0:0:0. Это связано с тем, что в часах пропадает питание, и отсчет времени прекратится. По этой причине нельзя вытаскивать батарею во время работы модуля.

Чтобы провести настройку времени на модуле, нужно в скетче найти строку

RTC.adjust(DateTime(__DATE__, __TIME__));

В  этой строке будут находиться данные с компьютера, которые используются ля прошивки модуля часов реального времени. Для корректной работы нужно сначала проверить правильность даты и времени на компьютере, и только потом начинать прошивать модуль часов. После настройки в мониторе отобразятся следующие данные:

Настройка произведена корректно и дополнительно перенастраивать часы реального времени не придется.

Считывание времени. Как только модуль настроен, можно отправлять запросы на получение времени. Для этого используется функция now(), возвращающая объект DateTime, который содержит информацию о времени и дате. Существует ряд библиотек, которые используются для считывания времени. Например, RTC.year() и RTC.hour() – они отдельно получают информацию о годе и часе. При работе с ними может возникнуть проблема: например, запрос на вывод времени будет сделан в 1:19:59. Прежде чем показать время 1:20:00, часы выведут время 1:19:00, то есть, по сути, будет потеряна одна минута. Поэтому эти библиотеки целесообразно использовать в случаях, когда считывание происходит нечасто – раз в несколько дней. Существуют и другие функции для вызова времени, но  если нужно уменьшить или избежать погрешностей, лучше использовать now() и из нее уже вытаскивать необходимые показания.

Пример проекта с i2C модулем часов и дисплеем

Проект представляет собой обычные часы, на индикатор будет выведено точное время, а двоеточие между цифрами будет мигать с интервалом раз в одну секунду. Для реализации проекта потребуются плата Arduino Uno, цифровой индикатор, часы реального времени (в данном случае вышеописанный модуль ds1307), шилд для подключения (в данном случае используется Troyka Shield), батарейка для часов и провода.

В проекте используется простой четырехразрядный индикатор на микросхеме TM1637. Устройство обладает двухпроводным интерфейсом и обеспечивает 8 уровней яркости монитора. Используется только для показа времени в формате часы:минуты. Индикатор прост в использовании и легко подключается. Его выгодно применять для проектов, когда не требуется поминутная или почасовая проверка данных. Для получения более полной информации о времени и дате используются жидкокристаллические мониторы.

Модуль часов подключается к контактам SCL/SDA, которые относятся к шине I2C. Также нужно подключить землю и питание. К Ардуино подключается так же, как описан выше: SDA – A4, SCL – A5, земля с модуля к земле с Ардуино, VCC -5V.

Индикатор подключается просто – выводы с него CLK и DIO подключаются к любым цифровым пинам на плате.

Скетч. Для написания кода используется функция setup, которая позволяет инициализировать часы и индикатор, записать время компиляции. Вывод времени на экран будет выполнен с помощью loop.

    #include     #include "TM1637.h"    #include "DS1307.h" //нужно включить все необходимые библиотеки для работы с часами и дисплеем.    char compileTime[] = __TIME__; //время компиляции.    #define DISPLAY_CLK_PIN 10    #define DISPLAY_DIO_PIN 11 //номера с выходов Ардуино, к которым присоединяется экран;    void setup()    {    display.set();    display.init(); //подключение и настройка экрана.    clock.begin(); //включение часов.    byte hour = getInt(compileTime, 0);    byte minute = getInt(compileTime, 2);    byte second = getInt(compileTime, 4); //получение времени.    clock.fillByHMS(hour, minute, second); //подготовка для записывания в модуль времени.    clock.setTime(); //происходит запись полученной информации во внутреннюю память, начало считывания времени.    }    void loop()    {    int8_t timeDisp[4]; //отображение на каждом из четырех разрядов.    clock.getTime();//запрос на получение времени.    timeDisp[0] = clock.hour / 10;    timeDisp[1] = clock.hour % 10;    timeDisp[2] = clock.minute / 10;    timeDisp[3] = clock.minute % 10; //различные операции для получения десятков, единиц часов, минут и так далее.    display.display(timeDisp); //вывод времени на индикатор    display.point(clock.second % 2 ? POINT_ON : POINT_OFF);//включение и выключение двоеточия через секунду.    }    char getInt(const char* string, int startIndex) {    return int(string[startIndex] - '0') * 10 + int(string[startIndex+1]) - '0'; //действия для корректной записи времени в двухзначное целое число. В ином случае на экране будет отображена просто пара символов.    }    

После этого скетч нужно загрузить и на мониторе будет показано время.

Программу можно немного модернизировать. При отключении питания выше написанный скетч приведет к тому, что после включения на дисплее будет указано время, которое было установлено при компиляции. В функции setup каждый раз будет рассчитываться время, которое прошло с 00:00:00 до начала компиляции. Этот хэш будет сравниваться с тем, что хранятся в EEPROM, которые сохраняются при отключении питания.

Для записи и чтения времени в энергонезависимую память или из нее нужно добавить функции EEPROMWriteInt и EEPROMReadInt. Они нужны для проверки совпадения/несовпадения хэша с хэшем, записанным в EEPROM.

Можно усовершенствовать проект. Если использовать жидкокристаллический монитор, можно сделать проект, который будет отображать дату и время на экране. Подключение всех элементов показано на рисунке.

В результате в коде нужно будет указать новую библиотеку (для жидкокристаллических экранов это LiquidCrystal), и добавить в функцию loop() строки для получения даты.

Алгоритм работы следующий:

  • Подключение всех компонентов;
  • Загрузка скетча;
  • Проверка – на экране монитора должны меняться ежесекундно время и дата. Если на экране указано неправильное время, нужно добавить в скетч функцию RTC.write (tmElements_t tm). Проблемы с неправильно указанным временем связаны с тем, что модуль часов сбрасывает дату и время на 00:00:00 01/01/2000 при выключении.
  • Функция write позволяет получить дату и время с компьютера, после чего на экране будут указаны верные параметры.

Заключение

Модули часов используются во многих проектах. Они нужны для систем регистрации данных, при создании таймеров и управляющих устройств, которые работают по заданному расписанию, в бытовых приборах. С помощью широко распространенных и дешевых модулей вы можете создать такие проекты как будильник или регистратор данных с сенсоров, записывая информацию на SD-карту или показывая время на экране дисплея. В этой статье мы рассмотрели типичные сценарии использования и варианты подключения наиболее популярных видов модулей.

13b5e0deaf19b06816d21e67ad4e211c_L.jpg

Arduino В данной статье мы подключим два модуля с таймерами реального времени (или real-time clock, RTC) – DS3231 и DS1307 – к Arduino. Оба модуля работают по интерфейсу I2C и питаются от батарейки формата 2032.

Нам понадобятся:

  • Arduino UNO или иная совместимая плата;
  • модуль ZS-042 с часами реального времени DS3231;
  • модуль с часами реального времени DS1307;
  • соединительные провода (рекомендую вот такой набор);
  • макетная плата (breadboard);
  • персональный компьютер со средой разработки Arduino IDE.

1Подключение к Arduino модуля ZS-042 с часами реального времени DS3231

Модуль ZS-042 с часами реального времени (RTC) имеет следующие характеристики:

  • Календарь до 2100 года с отсчётами секунд, минут, часов, числа месяца, месяца, дня недели и года (с учётом високосных годов);
  • 12- или 24-часовой формат;
  • 2 будильника;
  • напряжение питания: 3,3 или 5 В;
  • точность: ± 0.432 сек в день;
  • внутренний кварцевый генератор с частотой 32768 Гц;
  • поддерживаемый протокол: I2C со скоростью от 100 до 400 кГц;
  • габариты: 38×22×15 мм;
  • диапазон рабочих температур −40…+85°C.

На модуле присутствуют: микросхема таймера реального времени DS3231 (1 на рисунке), микросхема памяти AT24C32 объёмом 32 кбит (2 на рисунке), места для трёх перемычек A0, A1 и A2 (3 на рисунке), с помощью которых можно менять адресацию памяти микросхемы памяти; место для батареи питания размером 2032 (4 на рисунке).

zs-042.jpg
Внешний вид модуля ZS-042

Назначение выводов модуля такое:

Название Назначение
32K выход генератора 32 кГц;
SQW выход прямоугольного сигнала; частота задаётся с помощью регистра управления 0x0E и может составлять 1, 1024, 4096 или 8192 Гц;
SCL шина тактовых импульсов интерфейса I2C;
SDA шина данных интерфейса I2C;
VCC питание – 3,3 или 5 вольт;
GND земля.

С противоположной стороны модуля выводы SCL, SDA, питание и земля дублируются. На выходе 32K постоянно присутствует сигнал с встроенного кварцевого генератора:

32khz.jpg
Сигнал на выходе 32K модуля ZS-042

Теперь нужно подключить модуль к Arduino. Мы уже знаем, что линия SDA нужно подключать к пину A4 Arduino UNO и Nano, а линию SCL – к пину A5. Для питания возьмём выход 5V платы Arduino, землю модуля соединим с землёй Arduino.

ds3231_arduino_sch.jpg
Схема подключения модуля ZS-042 с таймером DS3231 к Arduino

Вот как это выглядит вживую:

ds3231_arduino.jpg
Модуль ZS-042 с таймером DS3231 подключён к Arduino

Рассмотрим диаграммы записи и чтения для таймера реального времени DS3231:

DS3231_i2c.png
Обзор передачи данных по последовательной шине I2C
DS3231_rw.png
Диаграмма записи и диаграмма чтения таймера реального времени DS3231

Как видно, тут всё стандартно для интерфейса I2C. Осталось только узнать, какие регистры за что отвечают, и мы будем готовы начать обмен данными с таймером DS3231. А вот и карта регистров:

DS3231_map.png
Карта регистров таймера реального времени DS3231

Первым делом нужно выставить дату и время. А затем нужно будет только читать значение времени и календаря. Расширенные функции – установка будильников и т.д. – всё это делается аналогично, поэтому останавливаться на этом не будем. Итак, чтобы выставить дату и время, нас интересуют регистры 0x00…0x06. Для записи значений в них, нужно послать команду записи, указать начальный адрес (0x00), а дальше – 7 байтов, сформированных для нужной даты и времени. Например, чтобы записать дату 02 января 2019 года, среда, и время 17 час 30 мин 02 сек, нужно отправить ведомому устройству с I2C адресом 0x68 массив: 00 02 30 17 03 02 01 19. Скетч, который реализует это, будет таким:

Вот как выглядит диаграмма записи этого массива в память таймера реального времени DS3231:

DS3231_set_time.png
Диаграмма выставления времени на RTC DS3231

Таймер запомнит выставленную дату и время. Если подключена батарейка, то данные будут храниться в памяти устройства до сброса или до полного разряда батареи, ведь в этом и есть назначение устройств такого рода. Давайте теперь будем с периодом 1 секунда читать значение времени и выводить в монитор последовательного порта. Для этого напишем вот такой скетч:

Скетч для чтения времени с часов DS3231 (разворачивается)

Обратите внимание, что каждую итерацию цикла loop() мы записываем адрес регистра 0x00. Если этого не делать, то мы будем каждый раз сдвигаться по карте регистров на 7 позиций, и возвращаемые данные будут совсем не те, что мы ожидаем.

Вот как выглядит в мониторе последовательного порта результат работы данного скетча:

read_time.png
Вывод даты и времени в монитор последовательного порта

А вот так выглядит временная диаграмма, порождаемая работой этого скетча:

read_time_diag.png
Временная диаграмма чтения регистров времени DS3231

Напоследок давайте немного усложним нашу программу и будем читать также значение температуры:

Скетч для чтения времени и температуры с часов DS3231 (разворачивается)

Вот как теперь выглядит вывод нашей программы:

read_time_temp.png
Вывод даты, времени и температуры в монитор последовательного порта

Само собой, в интернете полно библиотек для Arduino, которые упрощают работу с часами реального времени DS3231 и модулем ZS-042 в частности. Они делают всю рутинную работу, и вам не нужно будет разбираться с картой регистров и проводить манипуляции с перестановкой полученных байтов, чтобы получить удобочитаемое значение времени. В конце статьи дана ссылка на скачивание архива, в котором лежат несколько библиотек для работы с часами реального времени DS3231 и DS1307.

2Подключение к Arduino модуля с часами реального времени DS1307

Таймер DS1307 в отличие от DS3231 проще по функциональности: он имеет меньше регистров, не имеет встроенного датчика температуры и встроенного генератора тактовой частоты. Не имеет он также и функции будильника. Шина I2C функционирует только на частоте 100 кГц. Модуль с часами реального времени DS1307 может выглядеть вот так:

Внешний вид модуля с часами реального времени DS1307

Здесь номером 1 обозначена микросхема собственно таймера DS1307, номер 2 – микросхема памяти AT24C32 объёмом 32 кбит, 3 – кварцевый резонатор с частотой 32,768 кГц, 4 – держатель для батареи типа 2032.

На модуле имеются две группы контактов: P1 и P2. Группа P2 имеет стандартные выводы для шины I2C, плюс дополнительный вывод DS, к которому можно подключить внешний датчик температуры DS18B20. Группа P1 имеет большее число контактов:

Название Назначение вывода
SQ Выход прямоугольного сигнала 30 кГц;
DS подключение внешнего датчика температуры DS18B20;
SCL шина тактирования интерфейса I2C;
SDA шина данных интерфейса I2C;
VCC питание модуля – 3.3 или 5 вольт;
GND земля;
BAT вход питания от внешней батареи с напряжением в диапазоне 2,0…3,5 В.

Подключение этого модуля к Arduino осуществляется абсолютно так же, как и рассмотренного ранее: VCC модуля – 5V Arduino, GND – GND, SDA – A4, SCL – A5.

Теперь пришла пора познакомиться с устройством регистров часов DS1307. Карта регистров приведена на рисунке:

Карта регистров часов реального времени DS1307

Если присмотреться, увидим, что регистры 0x00…0x06 в точности совпадают с аналогичными регистрами рассмотренного таймера DS3231, а регистр 0x07 отвечает за частоту генерируемого прямоугольного сигнала. Кроме того, I2C адрес DS1307 также аналогичен адресу модуля DS3231. Поэтому логично предположить, что скетч установки времени подойдёт и здесь. В этом легко убедиться, если загрузить скетч в Arduino с подключённым модулем DS1307. Не забудьте только обновить установочный массив в соответствии с временем, которое будете выставлять на часах. Пример разобран в предыдущем разделе.

Скетч вывода времени также будет работать с этим модулем. После установки времени загрузим скетч и проверим это. Всё работает!

Модуль с таймером DS1307 подключён к Arduino

Библиотеки для работы с часами реального времени DS1307 и DS3231

В приложенном архиве лежат две разные библиотеки для Arduino (используйте ту, которая будет вам наиболее удобна), а также технические описания (datasheet) на микросхемы DS1307 и DS3231.

Скачать библиотеки для работы с часами реального времени DS1307 и DS3231 с Depositfiles</li> —>

Установка библиотек проводится стандартным способом: помещением директории с библиотекой в директорию libraries среды Arduino IDE или через меню . Проще всего начать знакомство с библиотекой с изучения примеров, которые появятся в меню после установки библиотеки. Там имеются примеры и установки времени, и чтения показаний часов.

Скачать вложения:

  • Библиотеки для работы с часами реального времени DS1307 и DS3231(1131 Скачиваний)

Последнее изменениеВторник, 01 Октябрь 2019 07:32 Прочитано 14427 разИспользуемые источники:

  • https://lesson.iarduino.ru/page/podklyuchenie-rtc-chasy-realnogo-vremeni-ds1302-ds1307-ds3231-k-arduino
  • https://arduinomaster.ru/datchiki-arduino/arduino-chasy-rtc-ds1307-ds1302-ds3231/
  • https://soltau.ru/index.php/arduino/item/524-kak-podklyuchit-chasy-realnogo-vremeni-rtc-k-arduino

Рейтинг автора
5
Подборку подготовил
Максим Уваров
Наш эксперт
Написано статей
171
Ссылка на основную публикацию
Похожие публикации