Часы реального времени — 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

Регистры хронометра 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 часы реального времени с последовательным интерфейсом

Популярно про I2C

Статья обновлена 02.04.2012

19 комментариев на « Часы реального времени — DS1307»

  1. Medved пишет 29.04.2011 в 13:14 #

    Этим часам путный кварц надо. Лучше всего из материнской платы.

  2. Konstantin пишет 07.02.2012 в 18:35 #

    Очень полезная статья. Спасибо.

  3. Konstantin пишет 10.02.2012 в 00:35 #

    Единственный вопрос, а что иногда башню у календаря сносит?
    Например 315 февраля 2012 года это сильно… 🙂

  4. Alex_EXE пишет 11.02.2012 в 20:25 #

    Не замечал такого, хотя пока и серьезно с ним не работал.
    Может быть вызвано задержками неправильными задержками, возможно, причина может быть из-за упрощенного алгоритма работы с I2C, может ещё какие-либо ошибки, так сказать не могу.
    Но 315 день, когда максимальное переданное значение может быть всего 255, говорит, что проблемы, скорее всего не в моём коде.

  5. Konstantin пишет 17.02.2012 в 17:22 #

    Да я именно вашу схему и запустил в протеусе 🙂

    Потом свой девайс наклепал, слегка усложнив местами, а местами упростив. Ошибка один в один, и с моим и с вашим устройством.

    (Усложнил — добавив таймер включения выключения. Упростил — экран на цифровых LED индикаторах с 74hc595 регистрах поставил)
    Как мне кажется ему бит подтваерждения в протоколе i2c желается 🙂

  6. Konstantin пишет 17.02.2012 в 17:26 #

    А может просто протеус косячит. Потому что и впрямь, и передаётся и принимается максимум 255, и у часов регистры 8 битные, поэтому странно… попробую собрать девайс. Сегодня — завтра… Посмотрю как в железе будет фунциклировать. Если нужно могу и свою схему выложить (с вашим i2c).

  7. Alex_EXE пишет 19.02.2012 в 14:35 #

    Да, бит подтверждения упустил, может быть, проблема в этом.
    Протеус идеально симулирует, в жизни все немного по-другому.

  8. AlexV пишет 29.03.2012 в 23:23 #

    Спасибо, статья очень полезная, на основе её делал часы на AVR. Вот только есть одна неточность, убил пол дня из-за этого:
    «Для включения часов следует установить бит CH в единицу.»
    Хотя название CH (clock halt) без инверсии уже говорит о том что будет если записать «1».
    Строка из даташита:
    When this bit is set to a 1, the oscillator is disabled.

  9. Alex_EXE пишет 02.04.2012 в 00:21 #

    Спасибо, что заметили, в тексте опечатался, исправил.

  10. Sergio пишет 30.01.2014 в 13:50 #

    Хороший проект.
    А кварц для PIC16F628A надо обязательно на 20Мгц?
    Нельзя использовать внутренний на 4МГц?

  11. Alex_EXE пишет 30.01.2014 в 16:17 #

    Осцилятор любой можно использовать, только, возможно, задержки придётся подкорректировать под новую тактовую частоту.

  12. Sergio пишет 30.01.2014 в 17:21 #

    Задержки в каких местах и каким образом?
    Смотрю по вашему коду, там большинство задержек в процедурах с i2c равно 1 NOP, при максимально выбранном кварце для данной микрухи, т.е. если у меня частота 4, а у Вас 20, то как я могу сделать задержку короче NOP в 5 раз?

    Схема на основе Вашей у меня собрана, кварц на DS1307 32768, а на PICе вобще кварца нет.
    В таком виде схема не пашет,т.е. на табло вместо цифр одни знаки вопроса.
    Вот сижу и чешу репу….
    Под рукой самый ближайший кварц к 20, есть только на 14.745.
    Его пытаться прикрутить?

    пс. Я просто многого пока не догоняю, т.к. ещё только в начале пути программирования PICов.

  13. Sergio пишет 01.02.2014 в 00:58 #

    Всё, разобрался. Запустил на внутреннем осциляторе на 4МГц.
    Паузы заменил на пустую функцию, дописал функнцию установки от этой же единственной кнопки календаря, плюсом прикрутил к пустым ногам микрухи термометр ТС77. Теперь часы-термометр с несбивающимися часами при выключении питания.

    Спасибо Вам за проект, он очень помог!!!

  14. Alex_EXE пишет 01.02.2014 в 02:57 #

    Пользуйтесь на здоровье, рад, что пригодилось.

  15. student пишет 09.07.2014 в 23:02 #

    Алекс вопрос к вам как к профи:) мой поэкт я сделал на основе нескольких в том числе вашего вот какая проблема получилась для того чтоб не нагружать камень слишком настроил прерывание внешнее по INT0 от тактового сигнала 1307(настроенного на 1Hz)
    чтоб данные о времени выводились на дисплей 1 раз в сек. Для вызова вот такой код
    isr(INT0_vect)
    {
    cli();
    time_show();
    sei();
    }
    на железе не проверял в протеус такая ошибка типа :попытка чтения после записи полубайта как побороть ума не приложу подскажите от куда можно копать? СПАСИБО

  16. student пишет 09.07.2014 в 23:05 #

    о и камень atmega8 писал в AVRStudio

  17. Alex_EXE пишет 16.07.2014 в 14:42 #

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

  18. sergey пишет 27.10.2014 в 01:57 #

    чёт не фурычит

  19. Andrii пишет 12.12.2014 в 01:25 #

    Уважаемый Sergio. Я в програмировании не очень. Ваш проект часов под 4 МГц и термометр ТС77 мне очень понравился. Немогли бы Ви выслать мне на електронку Ваш проект схеми и прошивку в hex. Заранеэ Вам благодарен. Моя електронка t2d2012@yahoo.com

Комментарии RSS

Оставьте отзыв