Порой хочется в разрабатываемом устройстве организовать подсчет текущего времени/даты. Если возложить эту обязанность на МК могут возникнуть проблемы с точностью хода часов, потерей данных при пропадании питания или банальная нехватка места в памяти микроконтроллера. Поэтому задачу по счету времени лучше всего оставлять микросхемам, которые заточены под такое дело. Например, популярная микросхема 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 минут и часы это схавают и не подавятся. Я не стал делать проверку с целью упрощения понимания кода.
Точность часов в основном зависит от точности примененного кварца, у себя я использовал кварц выдернутый с материнской платы, и за те два дня которые проходили часы идут секунду в секунду.
Программу для вывода русских символов на ЖКИ берем отсюда Ниже можно скачать прошивку с исходниками и проект в протеусе:
СкачатьВзято с: avrproject.ru
Последние статьи
- Лучшая практика проектирования при размещении компонентов печатной платы
- Android 6.0 на lancer X
- Простой усилитель мощности класса АВ своими руками.
- Двухтактный ультралинейный ламповый УНЧ на EL84 (6П14П).
- Люксметр на ATmega8 и цифровом датчике BH1750
- Контроллер для светодиодной ленты с ИК управлением
- Самодельный LED светильник на основе ИК датчика HC-SR501
- Простой усилитель низкой частоты на TDA7377 и NE5532
- Простейший звонок с двумя мелодиями
- LED Cube 8x8x8 на Arduino с RTC