;============== Программа часов
;AT90S2313 4 МГц
.include "2313def.inc"
;==== Управление сегментами ====
.equ segA = 5; PD5 (pin 9)
.equ segB = 6; PD6 (pin 11)
.equ segC = 2; PB2 (pin 14)
.equ segD = 4; PB4 (pin 16)
.equ segE = 5; PB5 (pin 17)
.equ segF = 6; PB6 (pin 18)
.equ segG = 7; PB7 (pin 19)
;==== Управление разрядами ====
.еqu em = 0; PD0 (pin2)
.equ dm = 1; PD1 (pin 3)
.equ eh = 2; PD2 (pin 6)
.equ dh = 4; PD4 (pin 8)
;==== Рабочие переменные ====
.def POS = r16 ;отсчет разрядов для динамической индикации
.def sek = r17 ;число секунд
.def temp = r18 ;рабочая переменная
.def emin = r19 ;число единиц минут
.def dmin = r20 ;число десятков минут
.def ehh = r21 ;число единиц часов
.def dhh = r22 ;число десятков часов
.def set_up = r23 ;отсчет разрядов при установке
.def count = r24 ;счетчик для мигания
.def Flag = r25 ;флаги режимов
;в регистре Flag: если бит0=1, то идет установка часов
;если бит1=1, то внешнее напряжение пропало
;======== Прерывания =========
rjmp RESET ;процедура Reset
reti
rjmp INTT1 ;прерывание INTI по нажатию Кн1
reti
rjmp TIM1 ;прерывание Timer1 по сравнению CompareA (счет времени)
reti
rjmp TIM0 ;прерывание Timer0 по переполнению (управл. разрядами)
reti
reti
reti
rjmp ACOMPI ;прерывание аналогового компаратора
;===== Программа =====
;===== прерывание по нажатию кнопки Кн1 ====
INTT1:
sbrc Flag,1 ;если бит1=1 напряжения нет
rjmp END_SET ;какая установка — на выход
clr temp
out GIMSK,temp ;запрещаем INTI
sbr Flag,1 ;устанавливаем бит 0 флага — идет установка
inc set_up ;отсчет, какой разряд устанавливаем
clr count ;очищаем счетчик мигания
cpi set_up,5 ;если счетчик разрядов
brne END_SET ;еще не больше 4, то на выход
clr set_up ;если больше, то обнуляем счетчик
ldi sek,59 ;и устанавливаем число секунд = 59
cbr Flag,1 ;сбрасываем бит 0 флага — конец установки
END_SET:
reti ;конец прерывания INT1
;===== прерывание Timerl — ход часов ====
TIM1:
sbrc Flag,1 ;если бит1=1 напряжения нет
rjmp mtime ;сразу посылаем на счет времени
sbrs Flag,0 ;если бит0=1 идет установка
rjmp mtime ;иначе сразу на счет времени
ldi temp, 0b10000000 ;на всякий случай
out GIFR,temp ;очищаем прерывание INT1
cpi count,0 ;если счетчик =0
breq CONT_1 ;то на продолжение
ldi temp,1<
out GIMSK,temp
CONT_1: ;установка
inc count ;увеличиваем счетчик мигания на 1
cpi set__up,1 ;если первый разряд, устанавливаем его
brne mm1 ;иначе на следующий
sbis PinB,0 ;если Кн2 нажата
inc emin ;увеличиваем число единиц минут на 1
cpi emin,10 ;если число единиц минут еще не равно 10
brne END_TIM1 ;то на выход из процедуры
clr emin ;если =10, то обнуляем
rjmp END_TIM1 ;на выход
mm1: cpi set_up,2 ;если второй разряд, устанавливаем его
brne mm2 ;иначе на следующий
sbis PinB,0 ;если Кн2 нажата
inc dmin ;увеличиваем число десятков минут на 1
cpi dmin,6 ;если число десятков минут еще не равно 6
brne END_TIM1 ;то на выход из процедуры
clr dmin ;если =6, то обнуляем
rjmp END_TIM1 ;на выход
mm2: cpi set_up,3 ;если третий разряд, устанавливаем его
brne mm3 ;иначе на следующий
sbis PinB,0 ; если Кн2 нажата
inc ehh ;увеличиваем число единиц часов на 1
cpi ehh,4 ;если число единиц часов еще меньше 4
brio END_TIM1 ;то на выход из процедуры
cpi dhh,2 ;если число десятков часов не равно 2
brne mm21 ;то на метку mm21
clr ehh ;иначе обнуляем число единиц часов
rjmp END_TIM1 ;на выход из процедуры
mm21: cpi ehh, 10 ;если число единиц часов не равно 10
brne END_TIM1 ;то на выход
clr ehh ;иначе обнуляем число единиц часов
rjmp END_TIM1 ;на выход
mm3: sbis PinB,0 ;четвертый разряд
inc dhh ;увеличиваем число десятков часов на 1
cpi dhh,3 ;если оно еще не равно 3
brne END_TIM1 ;то на выход
clr dhh ;иначе обнуляем
rjmp END_TIM1 ;на выход
;счет времени
mtime: inc sek ;увеличиваем число секунд на 1
cpi sek,60 ;если оно не равно 60
brne END_TIM1 ;то на выход
clr sek ;иначе обнуляем секунды
inc emin ;и увеличиваем единиц минут
cpi emin,10 ;если число единиц минут не равно 10
brne END_TIM1 ;то на выход
clr emin ;иначе обнуляем единиц минут
inc dmin ;и увеличиваем число десятков минут
cpi dmin,6 ;если оно не равно 6
brne END_TIM1 ;то на выход
clr dmin ;иначе обнуляем число десятков минут
inc ehh ;и увеличиваем число единиц часов
cpi ehh,4 ;если число единиц часов не равно 4
brio END_TIM1 ;то однозначно на выход
cpi dhh,2 ;если число десятков часов при этом не равно 2
brne mhh ;то на метку mhh
clr ehh ;иначе обнуляем число единиц часов
clr dhh ;и сразу число десятков часов тоже (это полночь)
rjmp END_TIM1 ;на выход
mhh:
cpi ehh,10 ;если число единиц часов не равно 10
brne END_TIM1 ;на выход
clr ehh ;иначе обнуляем единиц часов
inc dhh ;увеличиваем число десятков часов
END_TIM1:
reti ;выход из прерывания Timer1
;==== прерывание Timer0 управление разрядами ====
TIM0:
sbrc Flag,1 ;если бит1=1 напряжения нет
rjmp END_TIM0 ;тогда сразу на выход
clr temp ;все очищаем
out PortD,temp
out РогtB,temp
andi POS,3 ;счет разрядов от 0 до 3
sbis PinB,0 ;пока нажата кнопка Кн2
clr count ;разряд при установке не мигает
cpi P0s,0 ;если счетчик разрядов не 0
brne m0 ;то на метку m0 — следующий разряд
cpi set_up,1 ;если set_up=1, мигает этот разряд
brne sm_1 ;иначе на включение разряда
sbrs count,0 ;если бит 0 в count=0
sm_1: sbi PortD,em ;то уст. PDO в 1, разряд единиц мин. светится
;иначе он останется темным, т. е. мигает с частотой count
mov temp,emin ;в temp — число единиц минут
rcall SEG_SET ;устанавливаем сегменты
rjmp END_0 ;на выход
m0: cpi POS,1 ; если счетчик разрядов не 1
brne m1 ;то на сл. разряд
cpi set_up,2 ;если set_up=2, то мигает этот разряд
brne sm_2 ;иначе на включение разряда
sbrs count,0 ;если бит 0 в count=0
sm_2: sbi PortD,dm ;то уст. PD1 в 1, разряд десятков мин. светится
mov temp,dmin ;в temp — число десятков минут
rcall SEG_SET ;устанавливаем сегменты
rjmp END_0 ;на выход
m1: cpi POS,2 ;если счетчик разрядов не 2
brne m2 ;то на сл. разряд
cpi set_up,3 ;если set_up=3, то мигает этот разряд
brne sm_3 ;иначе на включение разряда
sbrs count,0 ;если бит 0 в count=0
sm_3: sbi PortD,eh ;то уст. PD2 в 1, разряд единиц часов светится
mov temp, ehh ;в temp — число единиц часов
rcall SEG_SET ;устанавливаем сегменты
rjmp END_0 ;на выход
m2: ;обработка 4 разряда десятков часов
cpi set_up,4 ;если set_up=4, то мигает этот разряд
brne sm_4 ;иначе на включение разряда
sbrs count,0 ;если бит 0 в count=0
sm_4: sbi PortD,dh ;то уст. PD4 в 1, разряд десятков часов светится
mov temp,dhh ;в temp — число десятков часов
rcall SEG_SET ;устанавливаем сегменты
END_0:
inc POS
END_TIM0:
reti ;выход из прерывания Timer0
;===== компаратор — батарейка =====
ACOMPI:
sbis ACSR,АСО ;если бит АСО =1, то продолжим
rjmp СОМР_1 ;иначе на установку мигания ldi temp,0b11000000
ut TCCR1A,temp ;двоеточие включено постоянно
rjmp END_comp ;на выход
СОМР_1:
ldi temp,0b01000000
out TCCR1A,temp ;двоеточие мигает
END_comp:
reti ;выход из процедуры компаратора
;===== процедура Reset ====
RESET:
cli ;запрещаем прерывания на время установки
ldi temp,low(RAMEND) ;загрузка указателя стека
out SPL,temp
ldi temp,0b01110111 ;порт D разряды 0,1,2,4,5,6 на выход
out DDRD,temp
ldi temp, 0b11111100 ;порт В все на выход, кроме 0,1 (компаратор)
out DDRB,temp
;- таймеры —
ldi temp,0Ь00000010 ;запуск Timer0 входная частота 1:8
out TCCR0,temp ;управление разрядами по переполнению,
;частота около 2 кГц (4/8=0,5 МГц/256)
ldi temp,high(62 500) ;старший байт
out OCR1AH,temp ;вых. частота 1 Гц при вх. частоте 1:64
ldi temp,low(62500) ;младший байт out
OCR1AL,temp
ldi temp,0b01000000
out TCCR1A,temp ;включаем переключающую моду для вывода ОС1 (15)
ldi temp,0b01001011 ;запуск 1/64 timer1 с обнулением при сравнении
out TCCR1B,temp;
;- прерывания —
ldi temp,1<
out GIMSK,temp
ldi temp,(1<
out TIMSK,temp
ldi temp,(1<
out ACSR,temp
sei ;разрешаем прерывания
;======= основной цикл ========
G_cycle: ;все время будем отслеживать пропадание внешнего питания
sbrs Flag,0 ;если бит0=1 идет установка
rjmp G_cycle ;если так, то ничего не делаем
sbic PinB,0 ;если напряжение есть
rcall Restore ;вызываем процедуру восстановления выходов
sbis PinB,0 ;если напряжения нет
rcall Disable ;вызываем процедуру отключения выходов
rjmp G_cycle ;зацикливаем программу
;======= конец основного цикла ========
Disable: ;процедура отключения
sbrc Flag,2 ;если бит1=1, то уже все сделали
rjmp END_dis ;выход из процедуры
cli ;запрещаем прерывания на время установок
sbr Flag,2 ;устанавливаем бит1 Flag
;обрываем внешние соединения и обнуляем все порты:
clr temp
out PortD,temp
out PortB,temp
out DDRD,temp
out DDRD,temp
sei ;разрешаем прерывания
END_dis:
ret ;конец процедуры отключения выходов
Restore: ;процедура восстановления
sbrs Flag,2 ;если бит1=0, то уже все остальное сделали
rjmp end_res ;выход из процедуры
;восстановление
cli ;запрещаем прерывания на время установок
cbr Flag,2 ;сбрасываем бит1 Flag
;восстанавливаем внешние соединения:
clr temp
ldi temp,0b01110111 ;порт D разряды 0,1,2,4,5,6 на выход
out DDRD,temp
ldi temp, 0b11111100 ;порт В все на выход, кроме 0,1
out DDRB,temp
sei ;разрешаем прерывания
END_res:
ret ;конец процедуры восстановления выходов
SEG_SET: ;процедура установки сегментов
cpi temp,0 ;ищем число, равное temp
brne ss_0
rcall OUT_0 ;и посылаем на нужную процедуру вывода сегментов
rjmp END_seg
ss_0: cpi temp,1
brne ss_1
rcall OUT_1
rjmp END_seg
ss_1: cpi temp,2
brne ss_2
rcall OUT_2
rjmp END_seg
ss_2: cpi temp,3
brne ss_3
rcall OUT_3
rjmp END_seg
ss_3: cpi temp,4
brne ss_4
rcall OUT_4
rjmp END_seg
ss_4: cpi temp,5
brne ss_5
rcall OUT_5
rjmp END_seg
ss_5: cpi temp,6
brne ss 6
rcall OUT_6
rjmp END_seg
ss_6: cpi temp,7
brne ss_7
rcall OUT_7
rjmp END_seg
ss_7: cpi temp,8
brne ss_8
rcall OUT_8
rjmp END_seg
ss_8: cpi temp,9
rcall OUT_9
END_seg:
jret ;конец процедуры установки сегментов
;процедуры для отображения цифр на семисегментном индикаторе
;ABCDEF(0);ВС(1)/ABDEG(2)/ABCDG(3)/BCFG(4);ACDFG(5)
;ACDEFG(6);ABC(7);ABCDEFG(8);ABCDFG(9)
Out_0:
sbi PortD,segA
sbi PortD,segB
sbi PortB,segC
sbi PortB,segD
sbi PortB,segE
sbi PortB,segF
ret
OUT_1:
sbi PortD,segB
sbi PortB,segC
ret
OUT_2:
sbi PortD,segA
sbi PortD,segB
sbi PortB,segG
sbi PortB,segE
sbi PortB,segD
ret
OUT_3:
sbi PortD,segA
sbi PortD,segB
sbi PortB,segG
sbi PortB,segC
sbi PortB,segD
ret
OUT_4:
sbi PortD,segB
sbi PortB,segC
sbi PortB,segF
sbi PortB,segG
ret
OUT_5:
sbi PortD,segA
sbi PortB,segF
sbi PortB,segG
sbi PortB,segC
sbi PortB,segD
ret
OUT_6:
sbi PortD,segA
sbi PortB,segF
sbi PortB,segG
sbi PortB,segC
sbi PortB,segE
sbi PortB,segD
ret
OUT_7:
sbi PortD,segA
sbi PortD,segB
sbi PortB,segC
ret
OUT_8:
sbi PortD,segA
sbi PortD,segB
sbi PortB,segC
sbi PortB,segD
sbi PortB,segE
sbi PortB,segF
sbi PortB,segG
ret
OUT_9:
sbi PortD,segA
sbi PortD,segB
sbi PortB,segC
sbi PortB,segD
sbi PortB,segF
sbi PortB,segG
ret