Часы реального времени
Вашему вниманию предлагается простая схема часов реального времени на основе микросхемы – хронометра DS1307 (RTS) (DD5), микроконтроллера ATmega8535 (DD4), дешифраторов двоичного кода в код семисегментного индикатора CD4511N (DD1, DD2) и светодиодных индикаторов с общим коллектором DC56 -11 RWA (DA2 – DA4), которые управляются ключами IRF7103 (DA5.1 – DA6). Будильник схемы состоит из управляемого генератора на микросхеме 4011 (DD3.3, DD3.4) и выходного каскада на IRF7103 (DA5.2), нагруженного на излучатель HCM1212A (Z1). Цепь сброса микроконтроллера, образована резистором R8, конденсатором С3 и микросхемой 4011 (DD3.1, DD3.2). Организация и стабилизация питания схемы +5В обеспечивается микросхемой L7805CV (DA1).
На светодиодных индикаторах высвечиваются часы (DA2), минуты (DA3), секунды (DA4), а при нажатии кнопки «Дата» (S6) – текущее число (DA2), месяц (DA3), год (DA4). Установка часов происходит при нажатии кнопoк: «Уст. часов» (S1), «->» (S3), «>» (S4), «<» (S5). Установка происходит от единиц к десяткам, в последовательности: число, месяц, год, час, минуты. Последним нажатием кнопки «->» происходит запуск часов: светодиод HL1 начинает мигать с частотой 1Гц.
Установка будильника происходит при нажатии кнопки «Уст. будильника» (S2). Кнопками «->», « >» , «<» устанавливаются часы и минуты . Последнее нажатие кнопки «->» включает будильник (светодиод HL2 светится). Сигналом будильника является тональный сигнал частотой 3 КГц . Сброс будильника осуществляется общим сбросом микроконтроллера: нажатием кнопки «Сброс» (S8).
Запись в RTS и чтение из RTS производится с помощью модуля TWI микроконтроллера. В DS1307 информация часов и календаря содержится в соответствующих регистрах в виде байта, причем единицы хранятся в младшем полубайте, а десятки в старшем полубайте. Это позволяет считывать информацию из RTS, затем сбрасывать её в PortA и с помощью дешифраторов DD1, DD2 аппаратно решить вопрос индикации.
Сделаем следующие определения регистров и обозначение выводов микроконтроллера:
.def lim=r1 ;предел десятков
.def temp=r16 ;первый рабочий регистр
.def logika=r17 ;второй рабочий регистр
.defSecond=r18 ;секунды
.defMin=r19 ;минуты
.defHoer=r20 ;часы
.defdata=r21 ;число
.defMonth=r22 ;месяц
.defYear=r23 ;год
.defDAT=r24 ;данные RTS
.defClkA=r25 ;адрес данных RTS
.def Delay1=r26 ;регистр формирования задержки 0,5 сек
.defDelay2=r27 ;то же
.defDelay3=r28 ;то же
.defBHoer=r29 ;часы будильника
.defBMin=r30 ;минуты будильника
.equ k1=PortB0 ;управление индикатором DA2 - часы (число)
.equ k2=PortB1 ;управление индикатором DA3 - минуты (месяц)
.equ k3=PortB2 ;управление индикатором DA4 - секунды (год)
Рассмотрим основные подпрограммы:
- установка текущего времени и даты
-установка будильника
-запись в RTS
-чтение из RTS
Подпрограмма установки текущего времени и даты включает в себя следующие блоки:
-установка числа
-установка месяца
-установка года
-установка часов
-установка минут
-запуск часов
Данная подпрограмма обрабатывает внешнее прерывание INT0 (нажатие кнопки S1 «Уст. часов»).Установка сводится к уменьшению или увеличению на 1 единиц и десятков того или иного значения (числа, месяца и т.д.) и последующей записью его в RTS.
Подпрограмма установки единиц.
Ed:
outPortA,logika ;индикация текущего значения
sbicPinD,4 ;кнопка «à» нажата?
rjmpBEd ;нет, переход к увеличению
rcallZad05 ;да, задержка 0,5с (от дребезга кнопки)
rjmpEnd ;и выход из подпрограммы
BEd: ;увеличение единиц текущего значения
sbicPinD,5 ;кнопка «>» нажата?
rjmpMEd ;нет, переход к уменьшению
rcallZad05
movtemp,logika ;копирование содержания logika в temp
andi temp,0b00001111;маскирование десятков
subi temp,-1 ;прибавляем 1
cpi temp,10 ; >9? (максимальное значение на индикаторе)
breqEd ;да, переход в начало
subilogika,-1 ;нет, прибавляем к logika 1
rjmpEd ;и переходим в начало
MEd: ;уменьшение единиц текущего значения
sbicPinD,6 ;кнопка «<» нажата?
rjmpEd ;нет, переход в начало
rcall Zad05
mov temp,logika
andi temp,0b00001111
subitemp,1 ;вчитаем 1
brcsEd ;если перенос, то – в начало (значений < 0 быть не может)
subi logika,1 ;вычитаем 1
rjmp Ed
End
ret
Подпрограмма установки десятков отличается от предыдущей разными пределами по максимуму, например: для десятков минут = 6, для десятков часов = 3 и т.д. .
Des:
outPortA,logika ;индикация текущего значения
sbic PinD,4 ;кнопка «à» нажата?
rjmpBDes ;нет, переход к увеличению
rcallZad05 ;да, задержка 0,5с
rjmp Ende ;и выход из подпрограммы
BDes: ;увеличение десятков
sbicPinD,5 ;кнопка «>» нажата?
rjmpMDes ;нет, переход к уменьшению
rcallZad05
movtemp,logika
anditemp,0b11110000;маскирование единиц
swaptemp ;сдвиг полубайта десятков вправо
subi temp,-1 ;прибавляем 1
cpse temp,lim ;temp=lim ?
subilogika,-0b00010000;нет, прибавляем 1 десяток
rjmpDes
MDes: ;уменьшение десятков
sbicPinD,6 ;кнопка «<» нажата?
rjmpDes ;нет, переход в начало
rcall Zad05
mov temp,logika
andi temp,0b11110000
swap temp
subi temp ,1 ;вычитаем 1
brcsDes ;если перенос, то переход в начало (значение не должно быть < 0)
subilogika,0b00010000;иначе вычитаем 1 десяток
Ende:
ret
В целом подпрограмма установки текущего времени и даты выглядит следующим образом:
StandClok:
outPortA,data ;индикация текущего числа
sbi PortB,k1
lditemp,4 ;максимальное значение десятков < 4
mov lim,temp
mov logika,data ;копируем data в logika
rcallEd ;установка единиц
rcallDes ;установка десятков
movdata,logika
movDAT,data ;запись текущего числа в RTS
ldiClkA,4 ;адрес текущего числа в RTS
rcallwrite_TWI ;подпрограмма записи в RTS
cbiPortB,k1 ;выключение индикации числа
………………………………………………………………………………………..
Другие блоки подпрограммы подобны данному и отличаются максимальным значением десятков и номером управления индикатором «к».
clrDAT ;запуск часов
ldiClkA,0 ;адрес секунд
rcallwrite_TWI
ldiDAT,0b00010000 ;установка частоты на выводе SQW=1 Hz
ldiClkA,7 ;адрес регистра управления
rcallwrite_TWI
reti
Подпрограмма установка будильника - StandBudi подобна подпрограмме StandClok и выполняется при обработке внешнего прерывания INT1 (нажатие кнопки S2 «Уст. будильника»). Сначала устанавливаются часы, затем минуты. Включается светодиод «Будильник» sbi PortC,3.
Подпрограммы записи в RTS и чтения из RTS.
Протокол i2c связи микроконтроллера с DS1307 осуществляется с помощью встроенного модуля TWI (TWO – WIRE serial Interface – двунаправленный последовательный интерфейс). Интерфейс TWI является полным аналогом базовой версии i2c фирмы Philips. Он позволяет объединить вместе до 128 различных устройств с помощью с помощью двунаправленной шины, состоящей всего из двух линий: линии тактового сигнала – SCL и линии данных – SDA. При этом микроконтроллер используется как ведущее (Master) устройство, а RTS – ведомое (Slave) устройство.
Блок управления (Control Unit) модуля TWI осуществляет управление всем модулем в соответствии с установками регистра управления TWCR и информацией, поступающей ему от остальных блоков модуля.
Биты регистра TWCR:
Бит 7. TWINT – флаг прерывания от модуля TWI. Этот флаг устанавливается аппаратно после выполнения очередной операции, когда модуль ожидает отклики со стороны программы. Если установлены флаги I регистра SREG и TWIE регистра TWCR, генерируется прерывание и осуществляется вызов соответствующего обработчика. Пока флаг TWINT установлен, на линии SCL удерживается низкий логический уровень. Сброс флага осуществляется записью в него лог. 1.
Бит 6. TWEA – разрешение бита подтверждения. Бит управляет формированием бита подтверждения. 1 – устройство формирует бит подтверждения; 0 – устройство виртуально отключается от шины TWI.
Бит 5. TWSA – флаг состояния «старт». При записи в TWSA лог. 1 модуль проверяет состояние шины и, если шина свободна, формирует состояние «старт». Если шина занята, то модуль TWI ожидает появления состояния «стоп» и только после этого формирует «старт». Флаг сбрасывается по окончании формирования «старт».
Бит 4.TWSTO – флаг состояния «стоп». В режиме ведущего запись лог. 1 приводит к формированию режима «стоп». Флаг должен сбрасываться программно по окончании режима «стоп».
Бит. 3. TWWC – флаг конфликта записи. Устанавливается в 1 при попытке записи в регистр данных TWDR, когда флаг TWINT сброшен. Флаг сбрасывается при записи в TWDR, когда флаг прерывания TWINT установлен.
Бит. 2. TWEN – разрешение работы модуля TWI. При записи в этот бит лог. 1 модуль TWI включается и берет на себя управление контактами ввода/вывода микроконтроллера SCL и SDA. При сбросе TWEN TWI выключается.
Бит. 1. Зарезервирован, читается как 0
Бит. 0. Разрешение прерывания от модуля TWI. Если в этом бите записана 1 и флаг I регистра SREG установлен, то прерывание от модуля разрешено.
Подпрограмма записи в RTS:
write_TWI:
rcallStart ;формирование условия «старт»
rcallwait ;ожидание сброса флага прерывания TWINT
rcallSLA_W;адресация ведомого устройства (RTS), разрешение записи
rcallAdres ;адресация регистра данных в RTS
rcallwait
rcallWdata ;посылка данных в регистр RTS
rcall Stop ;формирование условия «стоп»
ret
Stop:
ldi temp,(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
out TWCR,temp
ret
Start:
ldi temp,(1<<TWINT)|(1<<TWEN)|(1<<TWSTA)
out TWCR,temp
ret
SLA_W:
lditemp,0b11010000 ;адресация RTS, разрешение записи
out TWDR,temp
ldi temp,(1<<TWINT)|(1<<TWEN)
out TWCR,temp
ret
Adres:
outTWDR,ClkA ;задание адреса регистра RTS
ldi temp,(1<<TWINT)|(1<<TWEN)
out TWCR,temp
ret
Wdata:
out TWDR,DAT ;запись данных
ldi temp,(1<<TWINT)|(1<<TWEN)
out TWCR,temp
ret
wait:
in temp,TWCR
sbrs temp,TWINT ;проверяем состояниебита TWINT
rjmp wait
ret
Подпрграмма чтения из RTS:
read_TWI:
rcall Start
rcall wait
rcall SLA_W
rcall wait
rcall Start
rcall wait
rcallSLA_R ;адресация RTS и разрешение чтения
rcall wait
rcall Rdata ;чтение из RTS
sbiPortC,1 ;окончание чтения (SDA=1)
rcallStop
ret
Rdata:
lditemp,0b11010001 ;адресация RTS и разрешение чтения (1101000 – адрес RTS)
outTWDR,temp
lditemp,(1<<TWINT)|(1<<TWEN) ;сброс флага и разрешение работы модуля TWI
outTWCR,temp
ret
Rdata:
lditemp,0b11010001 ;адресация RTS и разрешение чтения (1101000 – адрес RTS)
outTWDR,temp
lditemp,(1<<TWINT)|(1<<TWEN) ;сброс флага и разрешение работы модуля TWI
outTWCR,temp
ret
Основная программа представляет цикл, состоящий из следующих блоков:
- считывание данных из RTS
- индикация часов, минут, секунд (если кнопка «Дата» S6 не нажата)
- индикация числа, месяца, года (если кнопка «Дата» нажата)
- сравнение текущего времени (часов, минут) с временем установленном в будильнике (если будильник включен – sbis PinC,3), включение генератора звука при равенстве.
Start1:
rcallLesung ;чтение данных из RTS
sbisPinD,1 ;кнопка «Дата» нажата?
rjmpIndD ;да, индикация даты
rcall IndClok ;нет – индикация времени
rjmpBudilo
IndD:
rcallIndData ;индикация даты
Budilo:
sbisPinC,3 ;будильник включен?
rjmpStart1 ;нет, переход в начало
cpseHoer,BHoer ;сравнение часов
rjmpStart1 ; часы неравны
cpseMin,BMin ;часы равны – сравнение минут
rjmpStart1 ;минуты неравны
sbiPortC,2 ; минуты равны - включение звука
rjmpStart
Подпрограмма чтения данных из RTS:
Lesung:
ldi ClkA,6 ;чтение года
rcall read_TWI
mov Year,DAT
Остальное – чтение месяца, числа, часов, минут, секунд - аналогично.
Подпрограмма индикации времени:
IndClok:
out PortA,Hoer ;индикация часов
sbi PortB,k1
rcall Zad010 ;задержка 10 мкс
cbi PortB,k1
rcall Zad001 ;задержка 1 мкс
out PortA,Min ;индикация минут
sbi PortB,k2
rcall Zad010
cbi PortB,k2
rcall Zad001
out PortA,Sec ond ;индикация секунд
sbi PortB,k3
rcall Zad010
cbi PortB,k3
ret
Подпрограмма индикации даты (IndData) подобна выше приведенной. В целом программа часов приведена в приложении.
Приложения:
Автор: Andre