Главная » Статьи » Как подключить

Работа с часами реального времени ds1307

  Порой хочется в разрабатываемом устройстве организовать подсчет текущего времени/даты. Если возложить эту обязанность на МК могут возникнуть проблемы с точностью хода часов, потерей данных при пропадании питания или банальная нехватка места в памяти микроконтроллера. Поэтому задачу по счету времени лучше всего оставлять микросхемам, которые заточены под такое дело. Например, популярная микросхема DS1307, которая способна вести подсчет реального времени в секундах, минутах, часах, датах месяца, месяцах, днях недели и годах с учетом высокосности текущего года вплоть до 2100 г. А автономное питание, которое обеспечивается 3-х вольтовой батарейкой, способно прокормить микросхему в течении 10 лет.

Обвязка минимальная: для работы требуется батарейка на 3 В и кварц на 32768 Гц. Для связи со внешним миром микросхема использует интерфейс I2C. Поэтому, следуя стандарту, линии связи должны быть подтянуты через резисторы 4,7К к шине питания.


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

I2cstart                                   ' даем режим готовности часам
I2cwbyte &HD0                              ' адрес микросхемы
I2cwbyte &H00                              ' адрес откуда начачинаем читать данные
I2cstart                                   ' даема сигнал старт на прочтение данных
I2cwbyte &HD1                              ' даем понять что готовы принимать данные
I2crbyte Seco , Ack                        ' ловим секунды
I2crbyte Mine , Ack                        ' минуты
I2crbyte Hour , Ack                        ' часы
I2crbyte Day , Ack                         ' день недели
I2crbyte Dat , Ack                         ' число месяца
I2crbyte Month , Ack                       ' месяц
I2crbyte Year , Nack                       ' год
I2cstop                                    ' закончили

  Здесь Seco, mine, hour, day, dat, month и year являются переменными типа byte, которые мы предварительно заводим для хранения данных. Команда Ack после приема байта сообщает микросхеме, что требуется отправить следующий байт. Приняв последний интересующий нас байт, останавливаем отправку командой Nack.  
  Так как данные в микросхеме хранятся в двоично-десятичном формате, с ними нужно проделать операцию преобразования в десятичный формат:

Seco = Makedec(seco)
Mine = Makedec(mine)
Hour = Makedec(hour)
Day = Makedec(day)
Dat = Makedec(dat)
Month = Makedec(month)
Year = Makedec(year)

  Теперь с этими данными можно делать все что угодно: выводить на дисплей, отправлять в терминал или сравнивать  с заданными значениями, получив таким образом будильник или напоминалку событий. 
 Но для начала работы, дату и время необходимо ввести в память микросхемы.  В данном проекте организована настройка по UART. В основном цикле происходит постоянное опрашивание микросхемы часов и вывод показаний на ЖКИ дисплей. В подпрограмме вывода на дисплей месяцам даны названия в соответствии с календарем: 1-январь, 2-февраль и так далее.
  Приход данных по UART вызывает прерывание, в обработчике которого происходит настройка времени и даты. Например, для настройки часов отправляем через терминал hour и получаем возможность ввести текущий час. Для минут отправляем min, а для секунд sec.
 

$regfile = "m32def.dat"
$crystal = 1000000
$baud = 1200

'* * * настройка пинов для подключния lcd
Config Lcd = 16 * 2
Config Lcdpin = Pin, Rs=Pinc.5, E=Pinc.4, Db4=Pinc.0, Db5=Pinc.1, Db6=Pinc.2, Db7=Pinc.3

Cls

'* * * подключаем библиотеку ds1307
$lib "ds1307clock.lib"

'* * * конфигурируем scl и sda пины
Config Sda = Porta.1 ' I2C Data
Config Scl = Porta.0 ' I2C Clock

'* * * заводим константы на биты чтения и записи ds1307
Const Ds1307w = &HD0 ' бит записи
Const Ds1307r = &HD1 ' бит чтения

'* * * заводим и разрешаем прерывания от UART
On Urxc Getchar
Enable Interrupts
Enable Urxc

'* * * заводим переменные для своих нужд
Dim C As Byte
Dim Seco As Byte
Dim Mine As Byte
Dim Hour As Byte
Dim Day As Byte
Dim Dat As Byte
Dim Month As Byte
Dim Year As Byte
Dim S As String * 5            ' переменная для работы с UART
Cursor Off
Lcd " ds1307 clock"
Wait 1
Cls

'* * * * * * основной цикл программы
Do
Gosub Ds1307                  'переход на подпрограмму считывания времени и даты
Gosub Displey                 'переход на подпрограмму отображения на дисплей
Loop

'-------------------------------------------------------------------------------
'* * * узнаем время и дату
Ds1307:
I2cstart
I2cwbyte Ds1307w
I2cwbyte &H00
I2cstart
I2cwbyte Ds1307r
I2crbyte Seco , Ack
I2crbyte Mine , Ack
I2crbyte Hour , Ack
I2crbyte Day , Ack
I2crbyte Dat , Ack
I2crbyte Month , Ack
I2crbyte Year , Nack
I2cstop
Seco = Makedec(seco)
Mine = Makedec(mine)
Hour = Makedec(hour)
Day = Makedec(day)
Dat = Makedec(dat)
Month = Makedec(month)
Year = Makedec(year)
Return

'-------------------------------------------------------------------------------
'* * * подпрограмма вывода на дисплей
Displey:
Locate 1 , 5                     ' выводим время
Lcd Hour ; ":" ;
If Mine < 10 Then
Lcd "0" ; Mine ; ":" ;
Else
Lcd Mine ; ":" ;
End If
If Seco < 10 Then
Lcd "0" ; Seco
Else
Lcd Seco
End If
Locate 2 , 3                     ' выводим дату
Lcd Dat
Locate 2 , 5
Lcd "-"
Locate 2 , 6                     ' обзываем каждый месяц
If Month = 1 Then
Lcd "ЗЅі"                        ' январь
End If
If Month = 2 Then
Lcd "дeі"                        ' февраль
End If
If Month = 3 Then
Lcd "јap"                        ' март и так далее
End If
If Month = 4 Then
Lcd "aѕp"
End If
If Month = 5 Then
Lcd "јaЗ"
End If
If Month = 6 Then
Lcd "ёЖЅ"
End If
If Month = 7 Then
Lcd "ёЖ»"
End If
If Month = 8 Then
Lcd "aіґ"
End If
If Month = 9 Then
Lcd "ceЅ"
End If
If Month = 10 Then
Lcd "oєї"
End If
If Month = 11 Then
Lcd "ЅoЗ"
End If
If Month = 12 Then
Lcd "гeє"
End If
Locate 2 , 9
Lcd "-" ; "20" ; Year
Return

'-------------------------------------------------------------------------------
'* * * обработчик прерывания UART
Getchar:
Input S                       ' то что пришло по UART
If S = "sec" Then             ' настроим секунды
Print "input sec..."
Input C
Seco = C
Seco = Makebcd(seco)          ' переводим данные в двоично-десятичный формат
I2cstart                      ' подаем сигнал старт
I2cwbyte Ds1307w              ' отправляем команду записи
I2cwbyte 0                    ' отправляем адрес куда пишем - &H00
I2cwbyte Seco                 ' записываем значение переменной по этому адресу
I2cstop                       ' закончили работать с I2C
cls
End If
If S = "min" Then             ' настроим минуты
Print "input min..."
Input C
Mine = C
Mine = Makebcd(mine)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 1                    ' адрес хранения минут &H01
I2cwbyte Mine
I2cstop
Cls
End If
If S = "hour" Then            ' настроим часы
Print "input hour..."
Input C
Hour = C
Hour = Makebcd(hour)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 2                    ' адрес хранения часов
I2cwbyte Hour
I2cstop
Cls
End If
If S = "dat" Then             ' настроим дату
Print "input dat..."
Input C
Dat = C
Dat = Makebcd(dat)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 4                    ' адрес хранения даты
I2cwbyte Dat
I2cstop
Cls
End If
If S = "month" Then          ' настроим месяц
Print "input month..."
Input C
Month = C
Month = Makebcd(month)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 5                   ' адрес хранения месяца
I2cwbyte month
I2cstop
Cls
End If
If S = "year" Then           ' настроим год
Print "input year..."
Input C
Year = C
Year = Makebcd(year)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 6                   ' адрес хранения года
I2cwbyte Year
I2cstop
Cls
End If
Return
End


 Здесь, как можно заметить, не предусмотрена защита от дурака, данные пришедшие через терминал и записываемые в микросхему не проверяются на истинность, тоесть можно легко ввести 30 часов 86 минут и часы это схавают и не подавятся. Я не стал делать проверку с целью упрощения понимания кода.



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


 
  Программу для вывода русских символов на ЖКИ берем отсюда
  Ниже можно скачать прошивку с исходниками и проект в протеусе:

Категория: Как подключить | Добавлено: 22.02.2011
Просмотров: 45130 | Комментарии: 42 | Теги: I2C, исходники, bascom-avr, DS1307 | Рейтинг: 5.0/6
Всего комментариев: 421 2 »
42 domrustika   (31.12.2013 02:44)
привет! подскажи пожалуйста еще ds1307 будет работать от аккумулятора мобильника заряженного до 4.08 В? и если да, на сколько его хватит?
потому что судя по даташиту - Когда питающее напряжение выше 1.25 * VBAT, устройство полностью доступно, и можно выполнять чтение и запись данных.
для нормальной работы DS1307 необходимо, чтобы напряжение батареи было в диапазоне 2.0 ... 3.5 В

вот и получается что часы будут работать даже от 2.5 В внешнего питания?
1.25 *2В = 2.5В - это если батарейка разряжена до 2 В :)

41 exersizze   (12.12.2013 14:02)
Тоже читал но не пробовал запускать генерацию. На странице 9 даташита на часы есть регистр Control, если записать в четвертый бит единицу, запускается генерация. Бит 1 и Бит 0 отвечают за частоту генерации, по умолчанию там нули и генерация составит 1 Гц. 
Этот регистр находится по адресу 07h, сразу после регистра хранящего год.
Код для запуска генерации должен быть такой (проверяйте)


Код
I2cstart
I2cwbyte &hD0  
I2cwbyte 7                   ' адрес регистра Control &H07
I2cwbyte &b000100     ' запуск генерации на 1 Гц
I2cstop


дока на часы http://datasheets.maximintegrated.com/en/ds/DS1307.pdf

40 max-x   (12.12.2013 00:55)
Читал, что на выходе SQW можно настроить генерацию ппрямоугольных импульсов с разной частотой. Подскажите пожалуйста как микросхему заставить генерировать меандр с частотой 1Гц.

39 Алексей_bird   (20.09.2013 23:49)
Это я заметил, но также заметил, что сравнение происходит при "вытягивании" из DS1307 текущего года, а не того, который мы хотим настроить. Т.е. мы указываем текущий год, указываем месяц и при выборе дня, уже есть ограничение 28 или 29, в зависимости от ранее указанного года, после жмем ок и данные вносятся в часы(DS1307). Хотя, мне кажется, это я что-то усложняю всё))) может это и актуально раз в год))))))

38 max   (20.09.2013 09:26)
Для Алексей_bird
Если Вы внимательно посмотрите за переменной Daysmonth, то увидите, что в зависимости от месяца она меняется. Если нужно, то вечером скину код с настройкой даты и времени, соответственно с проверкой.

37 Алексей_bird   (20.09.2013 00:50)
для max
Способ проверки на "високосность" интересный, только вот он у вас сделан для считывания и вывода даты непосредственно с DS1307. Да и DS1307 врядли выдаст неправильную дату. Вопрос как при настройке, когда указываешь год и месяц, была проверка на "високосность".

36 kip96   (19.09.2013 16:18)
Всем Привет! Знаете, наверное, что в библиотеке "ds1307clock.lib", если прописать config clock=user, то появляются все переменные часов(_sec, _min, и т.д.) Так же заведены подпрограммы settime. Если их в программе не указать, то компилятор ругается на их отсутствие. Как тогда устанавливать время? Я так понимаю просто написать time$ "00.00.00" и всё?, время установится? (смотрим сэмпл компилятора)

35 max   (16.09.2013 21:40)
В свое время тоже этим интересовался. Вот здесь: http://radiokot.ru/forum/viewtopic.php?p=950991#p950991 выкладывал код, который вычисляет високосный год и кол-во дней в месяце.

34 Алексей_bird   (16.09.2013 20:34)
Привет, коллеги! Пишу код с функцией часов, и вот какой возник вопрос: вижу код где дата, а именно день месяца устанавливается через условие
If Plus = 0 Then
Dat = Dat + 1
If Dat > 31 Then Dat = 1
........
End If
Но ведь есть месяца, в которых бывает и 28, и 29, и 30, и 31 день. Причем если с 30 и 31 днем всё понятно, то високосный год получается надо каждый раз вычислять? Так ведь получается? Ведь, если я запишу в DS1307 дату 30 февраля 2014 года, она ведь "проглотит" и даже не пожалуется на такое безобразие?

33 domrustika   (01.09.2013 12:41)
такой вопрос можно таким кодом сразу записать все данные в микросхему по нажатию кнопки? I2cstart
I2cwbyte &HD0
I2cwbyte 0
I2cwbyte 0
I2cwbyte Mine
I2cwbyte Hour
I2cwbyte Day
I2cwbyte Dat
I2cwbyte Month
I2cwbyte Year
I2cstop
этот код попробовал вроде работает, но через некоторое время после отключения питания часы и минуты не сохраняются)

32 ssql   (22.04.2013 13:45)
exersizze, спасибо!

31 exersizze   (22.04.2013 11:33)
Да, никаких отличий кроме исполнения корпуса. По поводу продолжительности автономного питания от батарейки, то если верить производителю до 10 лет

30 ssql   (21.04.2013 23:58)
Приветствую всех! Подскажите мне, на сколько хватит батарейки, которая питает 1307? У себя нашел только 1307Z. А они от 1307 отличается вроде только корпусом?

29 exersizze   (16.03.2013 09:38)
shinkaruk-ivan, адреса устройств разные? Если да то просто сажайте на одну линию.

28 max   (16.03.2013 09:04)
Матчасть почитать следует: http://easyelectronics.ru/interface-bus-iic-i2c.html

27 shinkaruk-ivan   (16.03.2013 03:48)
I2C Как я понял это параллельная шина, то все устройства подключать параллельно?
Мне нужно часы реального времени и микросхему синтезатор частот, который тоже по этой шине работает .

Посоветуйте пожалуйста как лучше подключить
Все подключить параллельно и кинуть на SCL и SDA
или синтезатор кинуть на SCL и SDA, а часы на другие свободные порты ?

26 mika222   (01.03.2013 20:17)
на версии 2.0.7.5 заработал только такой вариант.
I2cstart
I2cwbyte Ds1307w
I2cwbyte &H0
I2cstop ' вот этот стоп оказался очень необходим
I2cstart
I2cwbyte Ds1307r
I2crbyte Seco , Ack ' ловим секунды
I2crbyte Mine , Ack ' минуты
I2crbyte Hour , Ack ' часы
I2crbyte Day , Ack ' день недели
I2crbyte Dat , Ack ' число месяца
I2crbyte Month , Ack ' месяц
I2crbyte Year , Nack ' год
I2cstop

25 Anatoly   (07.06.2012 09:10)
Спасибо! Попробую разобраться!

24 exersizze   (06.06.2012 22:06)
Вот мой пример, только там опять код раздутый из-за использования дисплея от нокии3310 http://avrproject.ru/ds1307/ds1307button.zip

23 amv2000   (06.06.2012 16:40)
Или здесь пример от max50
http://radiokot.ru/forum/viewtopic.php?f=20&t=6408&start=120

22 amv2000   (06.06.2012 16:29)
Здесь на дисплее от Nokia http://bascom.at.ua/publ/chasy_na_mege8_ds1307_i_displee_nokia1100/1-1-0-71

21 Anatoly   (06.06.2012 10:38)
Спасибо, ясно! Еще такой вопрос, может есть у кого небольшой проектик ручной установки времени и даты?

20 Aleks8383   (01.06.2012 12:41)
Да могут и высвесчивать,тока там такая же система как и с месяцами.Из часов приходит цифра от 1 до 7,соответственно дни недели,а уже потом обзывай понедельниками ,вторниками итд.

19 Anatoly   (01.06.2012 11:14)
здравствуйте, в коде нашел строку
[code]I2crbyte Day , Ack ' день недели[/code]
значит часы еще высчитывают что сегодня пятница, суббота и тд?

+1   Спам
18 Gordon_shumway   (06.01.2012 22:38)
>глянь апнот на официальном сайте, там часы на 1307 с 12и часовым форматом, возможно чем-то поможет
>http://www.mcselec.com/index.p....emid=57

Спасибо ! Нашел, понял, заработало !!! biggrin На трех форумах задавал вопрос - никто не помог... Все оказалось проще пареной репы:

Code

Hour.6 = 1  'именно тут изменяем бит 6 - заносим 1
Hour.5 = 0  'а тут говорим, что у нас AM - заносим 0

Hour.6 = 1
Hour.5 = 0

I2cstart
I2cwbyte Ds1307w
I2cwbyte 2
I2cwbyte Hour
I2cstop

Do
Gosub Ds1307
Gosub Displey
Waitms 500

Loop

Ds1307:
I2cstart
I2cwbyte Ds1307w
I2cwbyte &H00
I2cstart
I2cwbyte Ds1307r
I2crbyte Seco , Ack
I2crbyte Mine , Ack
I2crbyte Hour , Nack
I2cstop
return
Hour = Hour And &B00011111 'убираем лишние биты

Seco = Makedec(seco)
Mine = Makedec(mine)
Hour = Makedec(hour)

+1   Спам
17 exersizze   (06.01.2012 19:00)
глянь апнот на официальном сайте, там часы на 1307 с 12и часовым форматом, возможно чем-то поможет
http://www.mcselec.com/index.p....emid=57

16 Gordon_shumway   (05.01.2012 21:23)
Доброго времени суток !

Подскажите плиз, как записать в шестой бит часов единицу ? Нужно перевести DS1307 в 12-часовой режим... Никак не соображу. angry

15 exersizze   (04.01.2012 22:49)
да, хорошо что все решилось smile

14 4ester   (04.01.2012 16:18)
действительно загрузил время через переменные Time$ и Date$ и ваша программа заработала, большое спасибо за подсказку.

13 4ester   (03.01.2012 18:02)
вы имеете ввиду через терминал? нет не загружал не удается, это может быть причиной? Я в принципе ничего не не менял в вашей программе, лишь изменял порты подключения, возможно действительно дело в том что я не загружал в микросхему предварительно данные.

1-30 31-42
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]






   EasyEDA:  бесплатный редактор схем

   ✓ Создание схем
   ✓ Возможность симуляции
   ✓ Быстрое создание печатных плат
   ✓ Интуитивно понятный интерфейс

   Нарисуй свою схему прямо сейчас!
   Изготовление печатных плат   https://easyeda.com/order
авторизация
Логин:
Пароль:
Комментарии
Когда не хватает ног. Часть 2. Сдвиговый регистр 74HC595
01.12.2016 - yorx:
Доброго времени суток, exersizze попробовал Ваш код все равно не работает как на...
Помни об усадке!
30.11.2016 - pchela5:
Автомобильные никакие не лезут?
Помни об усадке!
29.11.2016 - AlekS:
Виктор, спасибо.
С заменой транса в зиму, перестройка не комельфо) Валяет...
Управляем микроконтроллером с ПК по UART
29.11.2016 - exersizze:
Михаил, для работы с инфракрасными датчиками и диодами есть команды RC5SE...
Управляем микроконтроллером с ПК по UART
29.11.2016 - Михаил:
Всем привет.
Подскажите как переменную S передать по инфракрасному каналу...
Помни об усадке!
29.11.2016 - pchela5:
> Если ленту светодиодную порезать и соединить последовательно
Только ...
Когда не хватает ног. Часть 2. Сдвиговый регистр 74HC595
29.11.2016 - exersizze:
yorx, вывод Q7 ' первой микросхемы соединен с DS второй микросхемы? С...
Помни об усадке!
29.11.2016 - exersizze:
Можно даже без резистора их включать, если на ленте уже стоят. Но если опасаешьс...
Помни об усадке!
28.11.2016 - AlekS:
Да,пла, из абс как-то грубовато идет. (((
Самое главное, наверное и для т...


Лучшие цены на 3D принтеры
успей сделать себе подарок к Новому Году! ;)


Prusa i3

Prusa i3 от 12500 р.



Rostoсk

Rostock от 15000 р.