Занимательная микроэлектроника — страница 110 из 117

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<  ;иначе разрешаем прерывание INT1

    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<  ;разрешаем прерывание INT1

out GIMSK,temp

ldi temp,(1<  ;разр. прерываний Tim0 и Tim1

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  ;вызываем процедуру отключения выходов