Часы реального времени — DS1307
Во многих конструкциях полезно знать текущее время, но не всегда есть возможность, да и если контроллер будет сильно загружен, то часы будут постоянно отставать или спешить, что не очень хорошо. Выходом может стать внешний готовый источник времени – часы реального времени — DS1307.
Фотография модуля
Часы состоят из микросхемы DS1307, кварца на 32,768Кгц, батарейки и 2-х подтягивающих резисторов на линии SDA и SLC. Благодаря батарейке они продолжают идти при отключении внешнего питания. Также у DS1307 есть свободные 56 байтов энергозависимой статической ОЗУ, которые можно использовать в своих целях.
Типовая схема включения
Линии SCL и SDA – это I2C. На линии SQW – находиться тактовый импульс с частотой от 1 Гц до 32,768 Кгц, обычно она не используется.
Выводы микросхемы
У часов есть пара особенностей:
1. что бы они работали, в них должна быть батарейка или на крайний случай резистор на 4-10кОм, иначе они не будут работать и отвечать всяким мусором.
2. вокруг дорожек кварца должен быт замкнутый контур земли и корпус кварц тоже лучше подключить к земле
Немного теории
Хронометр имеет фиксированный адрес 68h, в 7 битовом адресе + 1 бит указывает на действие – чтение/запись.
Для записи используется следующий алгоритм:
Первый байт – адрес часов 68h + 0 бит указывающий на запись, итого D0h. После получения подтверждения передаётся адрес регистра. Это установит регистровый указатель. Затем начинается передача байтов данных, чтобы остановить его – генерируется условие окончания.
Для чтения:
Первый байт – адрес часов 68h + 1 бит указывающий на запись, итого D1h. После декодирования адреса и выдачи подтверждения устройство начинает передавать данные с указанного адреса (храниться в регистре указателя). Если перед началом чтения указатель регистра не записан, то первый читаемый адрес — это адрес, который был сохранён в нём последним. DS1307 должен принять «неподтверждение» для окончания чтения.
Регистры хронометра DS1307
Для включения часов следует установить бит CH в ноль, это следует сделать принудительно, т.к. часы после включения по умолчанию выключены.
Часы хранят информацию в двоично-десятичном виде – для получения данных достаточно прочитать соответствующий им регистр.
DS1307 может работать как в 24, так и в 12 часовом режиме – за это отвечает бит 12/24 (02h 6 бит). При 24 часовом режиме 5 и 4 биты регистра 02h соответствуют текущему десятку часа, при 12 часовом режиме 4 бит хранит десяток, а 5 признак до полудня / после полудня.
7 регистр отвечает за выходной тактовый генератор часов, SQW вывод. Бит OUT инвертирует выходной сигнал, бит SQWE включает тактовый генеретор, а биты RS0 и RS1 устанавливают частоту тактового импульса.
Практика
Был изготовлен небольшой модуль часов реального времени. На макетке были собраны часы с использованием микроконтроллера PIC16F628A, знакогенерирующего дисплея 2×16, одной кнопки для задания времени, модуля часов реального времени и с небольшим количеством обвязки.
Макетируемые часы
Схема
Печатка модуля
Плата содержит микросхему DS1307 в SMD исполнении. К ней подпаян кварц на 32,768 КГц, в корпусе DT-38, вокруг кварца должно быть кольцо земли и корпус самого кварц тоже стоит подключить к земле, для этого рядом с ним предусмотрено специальное отверстие. Для работы часов в автономном режиме предусмотрена батарейка на 3В CR120. Также для индикации работы модуля можно установить SMD светодиод с резистором на 470 Ом в корпусе типоразмера 0805.
PIC16F628A не содержит аппаратного I2C, поэтому он был реализован программно. Программный I2C был написан с нуля, он немного отличается от стандартного протокола, тем, что не ждёт подтверждения от слейва. Программный I2C будет рассмотрен в одной из следующих статей. На основе функций работы с I2C были реализованы следующие функции управления DS1307:
void ds_write(unsigned char addr,unsigned char data) { i2c_start(); i2c_write(0xD0); i2c_write(addr); i2c_write(data); i2c_stop(); } unsigned char ds_read(unsigned char addr) { unsigned temp; i2c_start(); i2c_write(0xD0); i2c_write(addr); i2c_stop(); i2c_start(); i2c_write(0xD1); temp=i2c_read(0); i2c_stop(); return temp; } void ds_off() { ds_write(0x00,ds_read(0x00)|0x80); } void ds_on() { ds_write(0x00,ds_read(0x00)&~0x80); } void ds_init() { unsigned char i; // устанавливаем режим 24 часа i=ds_read(0x02); if((i&0x40)!=0) { ds_write(0x02,i&~0x40); } // Если часы выключены - то включаем их i=ds_read(0x00); if((i&0x80)!=0) { ds_write(0x00,i&~0x80); } } unsigned char IntToBoolInt(unsigned char data) { data=data%100; return data/10*16+data%10; }
ds_write(адрес,байт данных) — отправляет 1 байт данных по указанному адресу DS1307
байт данных ds_read(адрес) — считывает 1 байт данных из указанного адреса DS1307
ds_off() — выключить DS1307
ds_on() — включить DS1307
ds_init() — инициализация DS1307
байт IntToBoolInt(байт) — функция перекодировки числа в двоично-десятичный вид
Во время инициализации проверяются и устанавливаются, если выключены следующие биты: бит отвечающий за 24-х часовой режим работы часов и бит отвечающий за включенное состояние часов. Были реализованы 2 функции для включения и отключения часов. DS1307 может отправлять и принимать как однобайтовые посылки, так и много байтовые, но для упрощения работы с часами функции для чтения и записи только однобайтовые. Для установки часов есть ещё функция для преобразования привычной десятичной формы представления числа в двоично-десятичную, в которой микросхема хранит показатели времени. Приведённых функция для работы с часами вполне достаточно.
В прошивки реализованы функции для считывания и вывода на дисплей времени – time() , даты – date(). В бесконечном цикле через некоторые промежутки времени эти функции вызываются для вывода времени и даты на дисплей. Рассмотрим, как устроена функция для чтения с последующим выводом текущего времени:
void time() { unsigned char i; SetLCDPosition(1, 0); i=ds_read(0x02); buffer[0] = i/16+'0'; buffer[1] = i%16+'0'; buffer[2] = ':'; i=ds_read(0x01); buffer[3] = i/16+'0'; buffer[4] = i%16+'0'; buffer[5] = ':'; i=ds_read(0x00); buffer[6] = i/16+'0'; buffer[7] = i%16+'0'; buffer[8] = '\0'; ShowStr(buffer); }
Происходит установка курсора на дисплее. Считываем значение регистра отвечающего за час и по пол байта, т.к. данные хранятся в двоично-десятичном виде, записываем в буфер. Далее добавляем разделитель в виде двоеточия. Считываем и записываем в буфер таким же образом значения минут и секунд. Выводим содержимое буфера на дисплей. Таким же образом устроена функция вывода текущей даты.
В прошивки есть функция для установки часов и минут – set_time(). Эта функция с помощью одной кнопки устанавливает время. Как это делается: нажимаем на кнопку – на дисплее высвечивается надпись «Set hour :» и количество часов, увеличиваем час по средством коротких нажатий на кнопку; установив час длительным нажатием переходим на установку минут, о чём свидетельствует надпись «Set min :», таким же образом устанавливаем минуты, а длительным нажатием возвращаемся в бесконечный цикл к часам. Но т.к. эта функция большая приведём из неё только одну строчку, которая записывает в DS1307 значение минут:
ds_write(0x02,IntToBoolInt(time));
Записываем в регистр, который соответствует минутам желаемое значение, предварительно приведённое к двоично-десятичному виду.
Скачать печатную плату в формате SL5
Скачать Исходники, прошивку и проект часов в Proteus 7.6
При написании статьи использовались следующие материалы:
DS1307 — 64 X 8 часы реального времени с последовательным интерфейсом
Статья обновлена 02.04.2012
Alex_EXE | 21.12.2010 | Микроконтроллеры |
Medved пишет 29.04.2011 в 13:14 #
Этим часам путный кварц надо. Лучше всего из материнской платы.
Konstantin пишет 07.02.2012 в 18:35 #
Очень полезная статья. Спасибо.
Konstantin пишет 10.02.2012 в 00:35 #
Единственный вопрос, а что иногда башню у календаря сносит?
Например 315 февраля 2012 года это сильно… 🙂
Alex_EXE пишет 11.02.2012 в 20:25 #
Не замечал такого, хотя пока и серьезно с ним не работал.
Может быть вызвано задержками неправильными задержками, возможно, причина может быть из-за упрощенного алгоритма работы с I2C, может ещё какие-либо ошибки, так сказать не могу.
Но 315 день, когда максимальное переданное значение может быть всего 255, говорит, что проблемы, скорее всего не в моём коде.
Konstantin пишет 17.02.2012 в 17:22 #
Да я именно вашу схему и запустил в протеусе 🙂
Потом свой девайс наклепал, слегка усложнив местами, а местами упростив. Ошибка один в один, и с моим и с вашим устройством.
(Усложнил — добавив таймер включения выключения. Упростил — экран на цифровых LED индикаторах с 74hc595 регистрах поставил)
Как мне кажется ему бит подтваерждения в протоколе i2c желается 🙂
Konstantin пишет 17.02.2012 в 17:26 #
А может просто протеус косячит. Потому что и впрямь, и передаётся и принимается максимум 255, и у часов регистры 8 битные, поэтому странно… попробую собрать девайс. Сегодня — завтра… Посмотрю как в железе будет фунциклировать. Если нужно могу и свою схему выложить (с вашим i2c).
Alex_EXE пишет 19.02.2012 в 14:35 #
Да, бит подтверждения упустил, может быть, проблема в этом.
Протеус идеально симулирует, в жизни все немного по-другому.
AlexV пишет 29.03.2012 в 23:23 #
Спасибо, статья очень полезная, на основе её делал часы на AVR. Вот только есть одна неточность, убил пол дня из-за этого:
«Для включения часов следует установить бит CH в единицу.»
Хотя название CH (clock halt) без инверсии уже говорит о том что будет если записать «1».
Строка из даташита:
When this bit is set to a 1, the oscillator is disabled.
Alex_EXE пишет 02.04.2012 в 00:21 #
Спасибо, что заметили, в тексте опечатался, исправил.
Sergio пишет 30.01.2014 в 13:50 #
Хороший проект.
А кварц для PIC16F628A надо обязательно на 20Мгц?
Нельзя использовать внутренний на 4МГц?
Alex_EXE пишет 30.01.2014 в 16:17 #
Осцилятор любой можно использовать, только, возможно, задержки придётся подкорректировать под новую тактовую частоту.
Sergio пишет 30.01.2014 в 17:21 #
Задержки в каких местах и каким образом?
Смотрю по вашему коду, там большинство задержек в процедурах с i2c равно 1 NOP, при максимально выбранном кварце для данной микрухи, т.е. если у меня частота 4, а у Вас 20, то как я могу сделать задержку короче NOP в 5 раз?
Схема на основе Вашей у меня собрана, кварц на DS1307 32768, а на PICе вобще кварца нет.
В таком виде схема не пашет,т.е. на табло вместо цифр одни знаки вопроса.
Вот сижу и чешу репу….
Под рукой самый ближайший кварц к 20, есть только на 14.745.
Его пытаться прикрутить?
пс. Я просто многого пока не догоняю, т.к. ещё только в начале пути программирования PICов.
Sergio пишет 01.02.2014 в 00:58 #
Всё, разобрался. Запустил на внутреннем осциляторе на 4МГц.
Паузы заменил на пустую функцию, дописал функнцию установки от этой же единственной кнопки календаря, плюсом прикрутил к пустым ногам микрухи термометр ТС77. Теперь часы-термометр с несбивающимися часами при выключении питания.
Спасибо Вам за проект, он очень помог!!!
Alex_EXE пишет 01.02.2014 в 02:57 #
Пользуйтесь на здоровье, рад, что пригодилось.
student пишет 09.07.2014 в 23:02 #
Алекс вопрос к вам как к профи:) мой поэкт я сделал на основе нескольких в том числе вашего вот какая проблема получилась для того чтоб не нагружать камень слишком настроил прерывание внешнее по INT0 от тактового сигнала 1307(настроенного на 1Hz)
чтоб данные о времени выводились на дисплей 1 раз в сек. Для вызова вот такой код
isr(INT0_vect)
{
cli();
time_show();
sei();
}
на железе не проверял в протеус такая ошибка типа :попытка чтения после записи полубайта как побороть ума не приложу подскажите от куда можно копать? СПАСИБО
student пишет 09.07.2014 в 23:05 #
о и камень atmega8 писал в AVRStudio
Alex_EXE пишет 16.07.2014 в 14:42 #
С аврами работал, но мало и давно (думаю, что в будущим к ним буду вынужден вернутся и закончить цикл статей по ним), по данному вопросу сейчас не подскажу, так что извиняйте.
Так же лучше приводить полный листинг исходника (но не вставлять его весь в комментарий) или его основные моменты, что бы было понятно, что происходит.
sergey пишет 27.10.2014 в 01:57 #
чёт не фурычит
Andrii пишет 12.12.2014 в 01:25 #
Уважаемый Sergio. Я в програмировании не очень. Ваш проект часов под 4 МГц и термометр ТС77 мне очень понравился. Немогли бы Ви выслать мне на електронку Ваш проект схеми и прошивку в hex. Заранеэ Вам благодарен. Моя електронка t2d2012@yahoo.com