Часы астрономического времени
В статье рассказано о том,как разработать часы астрономического времени с подсчетом секунд, минут, часов.
Для этого необходим генератор со стабильнойчастотой 1Гц. Его необходимо подключитьк устройству, подсчитывающему секунды –«счетчик секунд», код на выходе этого устройства будет эквивалентен количествусекунд. Также этот счетчик секунд должен иметь выход для счетчика минут, чтобыпо прошествии 60 секунд переключать его.Счетчик минут должен быть таким же, как счетчик секунд, и иметь абсолютно такуюже логику работы. Он также должен иметьвыход для счетчика часов. Счетчик часов не должен иметь выводов, он простодосчитывает до определенного значения (24), и обнуляется.
Таким образом, мы пришлик структурной схеме, представленной нарис.1
Алгоритм работы устройства
По запуску процессора мы «уходим» в подпрограммуинициализации (рис.2), где настраиваемнеобходимые порты ввода-вывода (для индикации секунд, минут, часов). Далеенастраиваем таймер на генерацию импульсов с частотой 1Гц.Погенерации каждого импульса последовательно запускаются подпрограммы вычисления секунд, минут, часов. В этих подпрограммахпроизводится вычисление и индикация значений минут, секунд, часов (рис.3).На рис.4 представлена подпрограмма вычисления секунд. По прошествии импульса от таймера,счетчик секунд увеличивается, его значения сравнивается с числом 60, и если оноравно, счетчик минут увеличивается,счетчик секунд обнуляется. Также обнуляются счетчики единиц и десятков секунд,и далее их значения выводятся в порты для индикации. Далее цикл начинается снуля.На рис.5 представлена подпрограмма вычисления минут.Она имеет абсолютно такое же строениеи логику работы, как иподпрограмма вычисления секунд. По прошествии часа (60минут по 60секунд), его значения сравнивается с числом 24 (рис.6), и если оноравно, счетчик часов обнуляется. Такжеобнуляются счетчики единиц и десятков часов, и далее их значения выводятся впорты для индикации. Далее цикл начинается с нуля. Если не равно, вычисляетсяколичество единиц и десятков часов, и эти значения выдаются в порты дляиндикации.
Рис.2 Рис.3
Рис.4 Рис.5
Разработка программы.
Программа начинается с директивы .include"m64def.inc". Этот файл содержит описание, имена, адреса всехрегистров и битов используемого микроконтроллера.
Далее по программе мы «именуем»необходимые нам регистрыкомандой .def . затем находятся ссылки на используемые нами прерывания (RESET-прерывание по сбросу и TIM1_COMPA – прерывание по совпадению Т1)
Вподпрограмме сброса выполняется настройка необходимых периферийных модулейконтроллера (настройка портов a, b, c, d, e, f, на выход, настройка таймера: режимсброс по совпадению,предделитель на 1024, разрешение прерывания по совпадению,занесение в регистр сравнения числа 963,при значении предделителя в 1024,
прерывание по совпадению будет генерироваться каждуюсекунду), далее настраивается указатель стека (необходим для правильной работыпрерываний и вложенных подпрограмм), разрешаются прерывания. На этом настройкаконтроллера заканчивается, счетчик команд уходит в основной цикл (enter: jmp enter).
Погенерации прерывания последовательно запускаются подпрограммы вычисления секунд(rcall count_sek), минут (rcall count_min), часов (rcall count_hours), позавершению работы этих подпрограмм, производится выход из подпрограммыобработки прерывания TIM1_COMPA, счетчик команд уходит в основной цикл.
Вподпрограмме вычисления секунд (count_sek) производится вычисление и индикациязначения числа секунд. При каждом вызове этой подпрограммы счетчик секундувеличивается (inc sekond), далее его значение сравнивается с числом 60, и еслине равно, происходит переход на метку nominut. Если же равно, перехода непроисходит, сбрасываются счетчикисекунд, единиц и десятков секунд (clr sekond, clr seked, clr sekdes),увеличивается счетчик минут, обновленные значения выдаются в порты споследующим выходом из подпрограммы. За меткой nominut расположена процедураподсчета и индикации числа секунд. Вместе со счетчиком секунд увеличивается изначение счетчика единиц секунд, если количество единиц секунд равно 10,увеличивается число десятков секунд, а число единиц секунд обнуляется. Далеезначения этих двух счетчиков выдаются в порты. Таким образом реализованапроцедура подсчета и индикации числа секунд.
В подпрограмме вычисления минут (count_min)вычисляется и выводится в порт для индикация количество минут. Подпрограмманачинается со сравнения количества минутс числом 60 (cpi sekond,60). Далее по программе расположен условный переход(brne nohour), т.о., если “60”,программа пропускает этот переход, далееувеличивается счетчик часов (inc hours), обнуляется счетчик минут, единицминут, десятков минут, обновленные значения выводятся в порт для индикации.Если же количество минут не равно 60, запускается процедура подсчета количестваединиц и десятков минут. Эта процедура состоит из сравнения числа единиц минутс десятью, если меньше десяти ,процедура завершается, если равно десяти, счетчик десятков минут увеличивается,счетчик единиц минут обнуляется, обновленные значения выводятся в порты дляиндикации, производится выход из подпрограммы.
Далее выполняется подпрограмма вычисления часов. Сначала числочасов сравнивается с числом 24 (cpi hours,24). Если равно, ход программыпродолжается, счетчик часов обнуляется ,также обнуляются счетчик единиц и десятков часов, эти значения выдаются в портыдля индикации. Если не равно, вычисляется количество единиц и десятковчасов, эти значения также выдаются впорты для индикации.
.include "m64def.inc"
.def oper=r16 ;r16 - регистр для операций
.def sekond=r17 ;r17- регистр - счетчик секунд
.def minute=r18 ;r18- регистр - счетчик минут
.def hours=r19 ;r19 - регистр - счетчик часов
.def seked=r20 ;r20- регистр - счетчик едениц секунд
.def sekdes=r21 ;r21- регистр - счетчик десятков секунд
.def mined=r22 ;r22- регистр - счетчик едениц минут
.def mindes=r23 ;r23- регистр - счетчик десятков минут
.def houred=r24 ;r24- регистр - счетчик едениц часов
.def hourdes=r25 ;r25 - регистр - счетчик десятков часов
;=======================================
.org 0x0000
jmp RESET ; ResetHandler
.org 0x0018
jmp TIM1_COMPA ; Timer1Compare A Handler
;
RESET:
;==============================
ldi oper,255 ;настройка портов a,b,c,d,e,f,на выход
out ddrb,operout ddra,oper
out ddrc,oper
out ddrd,oper
out ddre,oper
sts ddrf,oper
;==============================
;настройка таймера Т1
ldi oper,high (963)
out ocr1ah,oper
ldi oper,low (963) ;1000/1024=963
out ocr1al,oper ;такимобразом, каждую 1с - прерывание
ldi oper,(1<<wgm12)+(1<<cs12)+(1<<cs10)
out TCCR1B,oper ;режимсброс по совпадению,предделитель на 1024
ldi oper,(1<<ocie1a);разрешение прерывания посовпадению
out timsk,oper
;==============================
ldi r16, high(RAMEND) ;инициализация стека,
out SPH,r16
ldi r16, low(RAMEND)
out SPL,r16
sei ;разрешениепрерываний
enter: ;сновнойцикл программы
jmp enter
TIM1_COMPA: ;прерываниепо совпадению Т1
rcall count_sek ;подпрограммывычисления секунд
rcall count_min ;подпрограммывычисления минут
rcall count_hours ;подпрограммывычисления часов
reti ;выходиз прерывания
count_sek: ;подпрограммывычисления секунд
inc sekond ;увеличитьсчетчик секунд
cpi sekond,60 ;счетчиксекунд = 60?
brne nominut ;еслинет, перейти на метку nominut
clr sekond ;обнулитьсчетчик секунд
clr seked ;обнулитьсчетчик единиц секунд
sts portf,seked ;отобразитьсчетчик единиц секунд
clr sekdes ;обнулитьсчетчик десятков секунд
out porte,sekdes ;отобразитьсчетчик десятков секунд
inc minute ;увеличитьсчетчик минут
inc mined ;увеличитьединиц минут
jmp ind0 ;перейтина метку ind0
nominut:
inc seked ;увеличитьсчетчик едениц секунд
cpi seked,10 ;счетчикединиц секунд = 10?
brne ind0 ;еслинет, перейти на метку ind0
inc sekdes ;увеличить счетчик десятков секунд
clr seked ;обнулитьсчетчик единиц секунд
out porte,sekdes ;отобразитьсчетчик десятков секунд
ind0:
sts portf,seked ;отобразитьсчетчик единиц секунд
ret ;выходиз подпрограммы подсчета секунд
count_min: ;подпрограммывычисления минут
cpi minute,60 ;счетчикминут = 60?
brne nohour ;еслинет, перейти на метку nohour
inc hours ;увеличитьсчетчик часов
inc houred ;увеличитьсчетчик едениц часов
clr minute ;обнулить счетчик минут
clr mined ;обнулить счетчик единиц минут
out portd,mined ;отобразить счетчик единиц минут
clr mindes ;обнулить счетчик десятков минут
out portc,mindes ;отобразить счетчик десятков минут
inc minute ;увеличить счетчик минут
jmp ind1 ;перейтина метку ind1
nohour:
cpi mined,10 ;счетчикедениц минут = 10?
brne ind1 ;если нет, перейти на метку ind1
inc mindes ;увеличитьсчетчик десятков минут
clr mined ;обнулитьсчетчик единиц минут
out portc,mindes ;отобразитьсчетчик десятков минут
ind1:
out portd,mined ;отобразитьсчетчик единиц минут
ret ;выходиз подпрограммы подсчета минут
count_hours: ;подпрограммывычисления часов
cpi hours,24 ;счетчикчасов = 60?
brne noday ;еслинет, перейти на метку noday
clr hours ;обнулитьсчетчик часов
clr houred ;обнулитьсчетчик едениц часов
out porta,houred ;отобразитьсчетчик едениц часов
clr hourdes ;обнулитьсчетчик десятков часов
out portb,hourdes ;отобразитьсчетчик десятков часов
jmp ind2 ;перейтина метку ind2
noday:
cpi houred,10 ;счетчикедениц часов = 10?
brne ind2 ;еслинет, перейти на метку ind2
inc hourdes ;увеличитьсчетчик часов
clr houred ;обнулитьсчетчик едениц часов
out portb,hourdes ;отобразитьсчетчик десятков часов
ind2:
ret ;выходиз подпрограммы подсчета часов
Схема электрическая принципиальная