Всех приветствую!
Сегодня мы поработаем с модулем Arduino часов реального времени DS3231. Эти часы имеют хорошие ходовые характеристики благодаря тому, что кварц имеет аппаратную температурную компенсацию. В зависимости от температуры корпуса, которую измеряет встроенный датчик, происходит коммутация ёмкостей к ногам микросхемы, тем самым убирая дрейф частоты. Выглядит такой модуль так:
Тем, кто читал мои статьи раньше,
уже знает, что для устройств с интерфейсом I2C написана библиотека I2C.L. Тем же, кто впервые об этом узнаёт, ссылка на материалы будет опубликована в конце статьи. Там же в архиве будет и эта библотека. Напомню, что для работы с этими исходниками нужна ОС DSDOS, ASSM v2.7, текстовый редактор ED$ и набор SDK DSDOS.
Для начала подключим наш модуль к Ориону по следующей схеме, предварительно вставив батарейку CR2032 в модуль:
Т.к. на самом модуле выполнены все необходимые подтяжки сигналов к питанию, нам этого делать не нужно.
Для тестирования и работы часов напишем три программы: MEM3231$ для просмотра ячеек памяти часов, SET3231$ для установки даты и времени и RTC3231$ - сама программа работы с часами - отображение календаря и температуры.
Программа MEM3231$.
Показывает содержимое ячеек памяти часов. После запуска результат работы выглядит так:
Всего в часах 19 ячеек памяти.
По приведённой таблице, взятой из даташита, можно понять, какая ячейка за что отвечает. Нас интересуют 00-06(календарь) и 11-12(термометр). Будильника на Орионе у нас не будет, поэтому остальные ячейки мы игнорируем.
После первого включения светодиод VD2 скорее всего будет погашен и внутренний тактовый генератор также не будет активирован. Поэтому для запуска часов первой всегда должна запускаться процедура инициализации. Вот её текст:
DS3231_INIT:
CALL I2C_INIT
CALL DS3231_SQW_EN
RET
В процедуре инициализируется шина I2C и происходит выполнение включения выхода SQW, который с периодичностью 1сек будет включать светодиод.
DS3231_SQW_EN:
PUSH D
MVI D,0Eh
CALL DS3231_RD_ADDR
MOV A,E
ANI 0 ;INTCN=0
MOV E,A
MVI D,0Eh
CALL DS3231_WR_ADDR
POP D
RET
Ранее вместо команды ANI 0 была команда ANI 0FBh, которая сбрасывала только один бит INTCN, но опыт работы показал, что лучше всего обнулять весь регистр 0Eh. Таким образом можно всю процедру упростить до
DS3231_SQW_EN:
PUSH D
MVI D,0Eh
MVI E,0
CALL DS3231_WR_ADDR
POP D
RET
Но я этого делать не стал из-за возможности возвращения к старому варианту, ведь могут быть варианты в работе с этим регистром. Он не только запускает часы, но и переводит вывод SQW в режим срабатывания будильника, выбор будильника и выбор частоты на выводе SQW.
Процедуры установки и чтения даты/времени в исходнике посмотрите сами. Они длинные, здесь показывать не буду.
Давайте разберём работу термометра.
Дело в том, что в данной микросхеме DS3231 термометр не в любой момент времени доступен. Перед измерением необходимо запросить состояние бита BSY в регистре 0Fh:
Процедура ожидания сброшеного бита BSY:
WAIT_BSY_0:
PUSH D
WB0:
MVI D,0Fh
CALL DS3231_RD_ADDR
MOV A,E
ANI 4
JNZ WB0
POP D
RET
Когда бит BSY сброшен, можно производить измерения.
Измерение производится установкой бита CONV в регистре 0Eh. После этого необходимо выдержать паузу 5мс и считать регистры 11h и 12h.
В отличие от других регистров, которые передаются в формате BCD (двоично-десятичный код), регистры 11h и 12h передаются в формате HEX и для нормального отображения требуют конвертации по формуле:
if (msb & 0x80)
return -(256 - ((float)msb + ((lsb >> 6) * 0.25f))); // отрицательная
else
return (float)msb + ((lsb >> 6) * 0.25f); // положительная
Т.к. на Орионе отрицательную температуру не приходится измерять (но если очень изловчиться, то, конечно, можно 🙂), я взял конвертацию только положительной температуры.
Теперь разберём работу программы SET3231$.
Это программа установки даты/времени. После запуска мы увидим приглашение для ввода времени:
Если показания времени вводить не нужно, надо нажать [F4] или [AP2](Ecs), программа перейдёт в режим ввода даты. Регистры часов останутся без изменений.
Здесь небольшое пояснение. Помимо самой даты нужно еще вводить номер дня недели - это параметр "Н". Дни недели нумеруются так: от понедельника до субботы это от 1 до 6, а воскресенье это 0. Например, надо ввести дату на момент написания статьи - это четверг, число 17, месяц 04, год 25. Так и вводим: 4/17/04/25.
Следует заметить, что незначащие нули также нужно вводить. Что касается разделителя, то вместо ":" в часах и "/" в дате, можно использовать пробел, например: "10 30 45" для часов и "4 17 04 25" для даты. Ещё раз: разделитель обязателен!
Третья программа RTC3231$.
Эта программа отображает показания часов и термометра. Можно использовать как скринсейвер 🙄
Выход из программы, как видно из подсказки на фото - нажатие любой клавиши. Возможно, придётся немного придержать клавишу, чтобы выйти.
А вот видео с небольшой демонстрацией:
Все материалы для ознакомления можно скачать по ссылке: https://disk.yandex.ru/d/PGIzbUCs_pZvBg
Это была третья статья, посвящённая работе устройствам по протоколу I2C.
Первые две можно прочесть по ссылкам:
До новых встреч!