Текст программы такой:
Спойлер
.include "tn15def.inc".equ out_lamp = 3; выход управления освещением
.equ out_vent = 4; выход управления вентилятором
.def flags = R22; регистр флагов
.equ power = 0; flags для фильтрации помех
.equ vent = 1; flags,1 флаг включения вентилятора
.def mode = R23 ; переменная для хранения режима работы 01- лампа, 10 - вентилятор, 11 - лампа и вентилятор
.equ vent_mode = 0;mode,0 вентилятор
.equ lamp_mode = 1;mode,1 лампа
.def delay = R19 ; переменная для хранения времени задержки до 22 мин
.def delay_H = R20; переменная для хранения времени задержки выше 22 мин
.def ms_delay = R21 ; переменная для хранения времени задержки выключения выключателя
.def temp = R16 ; регистр временного хранения
.def temp_int = R17 ; временная переменная для использования в прерывании
.def temp_sreg = R18 ;временная для SREG
.cseg
.org 0
;векторы прерываний
rjmp init ; reset On
rjmp int_int0 ; INT0
reti; I/O pins off
reti; Timer1 compA Off
rjmp int_timer1; Timer1 overlow
rjmp int_timer0; Timer0 overlow
reti; EEPROM ready Off
reti; Analog Comp Off
reti; ADC conversion Off
;инициализация при первом запуске
init:
; ldi temp, 0x67
; out OSCCAL,temp ; тактовая частота для протеуса
sbi ACSR,ACD ;отключить компаратор
; ldi temp,0b10000000
; out ACSR,temp;для отладки в мплабе, в протеусе работает верхняя строчка. (в железе пробовал и так, и так, не влияет)
ldi temp,0b01000000 ;настройка прерываний
out gimsk,temp ; разрешить внешнее прерывание по INT0
ldi temp,0b00000011
out MCUCR,temp ; настройка прерывания INT0 по фронту
; ldi temp,(1<<INTF0)
; out GIFR,temp ; для протеуса, почему-то устанавливается флаг прерывания при разрешении прерываний по INT0, поэтому его опускаем принудительно (в железе пробовал и так и так, не влияет)
ldi temp,( 1<<TOIE1|1<<TOIE0)
out timsk,temp ; разрешить прерывания при переполнении таймеров TMR0 и TMR1
ldi temp,0b00011000 ;настройка порта
out ddrb,temp;PB3,PB4 на выход
ldi mode,3; запись режима лампа + вентилятор
;_____включили выключатель, запускаем систему, согласно режима работы ________
on:
;выдержка таймера устанавливается в зависимости от режима
clr temp
out tcnt1,temp; обнуление таймеров
out tcnt0,temp
ldi ms_delay,1 ; задержка 164мс
; ldi delay,255; 5,12 сек*255 = 22мин пока отключана
ldi delay,2; для проверки,основной режим работы 10 сек.
; sbrc mode,lamp_mode; если включено освещение включаем 1 час выдежки
; ldi delay_H,2; 22мин*3 = 64мин.(2-1-0 3 такта)
; для проверки, пока отключена
;______________________
ldi temp,(1<<CS02|1<<CS01|1<<CS00)
out tccr0,temp ;запуск таймера с внешним входом по фронту
sei ; разрешаем прерывания
on_wait: ;ожидаем наличия сетевого напряжения
sbrs flags,power
rjmp on_wait
; ldi temp,(1<<PSR1)
; out SFIOR,temp ; сброс прескаллера на всякий случай, пробовал - не влияет, отключил
ldi temp,(1<<CS13|1<<CS12|1<<CS11|1<<CS10)
out tccr1,temp ;запуск таймера TMR1 с предделителем СК/1024, переполнение через 164 мс по эмуляции 2,8 сек, в железе вроде нормально
sbrc mode,lamp_mode
sbi PORTB,out_lamp
sbrc mode,vent_mode
sbi PORTB,out_vent ; запуск вентилятора и лампы согласно режима работы
stopwait:
tst delay_H ;проверка срабатывания таймера общей выдержки
brne off_on_en
tst delay
breq stopall
off_on_en:
tst ms_delay ;проверка срабатывания выключателя
breq off_on
rjmp stopwait
;========обработка включения/выключения выключателя===========
off_on:
cli ; запретить прерывания
cbi portb,out_vent; выключаем все
cbi portb,out_lamp
clr temp
out tccr0,temp
out tccr1,temp ; стоп таймеры
cbr flags,(1<<power)
dec mode ;переключение режима от большего числа к меньшему
tst mode
brne on
ldi mode,3;кольцевание режима 3-2-1-3 и т.д.
rjmp on
;=====================
;__________________ После отработки таймера выдержки____________
stopall:
cbi portb,out_lamp; выключаем освещение
sbrc mode,vent_mode; если вентилятор был включен - выключаем на 22 мин.( пока 5 сек)
rjmp vent_off
;__________________ждем выключения-включения выключателя _______
stop_1: ;отработка включения/выключения выключателя
tst ms_delay
brne stop_2
rjmp off_on
stop_2:; выключатель не выключался
; вентилятор включить на 1 мин каждые 22 мин. (пока 5 сек включен, 5 сек выключен)
tst delay ;проверка таймера
brne stop_1
sbrc flags,vent
rjmp vent_off
sbi PORTB,out_vent;включение вентилятора
sbr flags,(1<<vent); установка флага включенного вентилятора
ldi delay,1 ; для проверки. время работы вентилятора 5 сек.
; ldi delay,12; установка выдержки 1 мин (пока отключено)
rjmp stop_1
vent_off:;выключение вентилятора на 22 мин.
cbi PORTB,out_vent
cbr flags,(1<<vent);сброс флага включеного вентилятора
ldi delay,1 ;для проверки, время паузы вентилятора 5 сек
; ldi delay,255; установка выдержки 22 мин. (пока отключено)
rjmp stop_1
;_________________________________
;+++++++ Обработка прерываний +++++++++++++++++++++++++++++++
int_int0:
;каждый фронт импульса сети сбрасывает счетчик задержки выключателя
in temp_sreg,SREG
clr temp_int
out tcnt1,temp_int
ldi ms_delay,1
sbr flags,(1<<power)
out SREG,temp_sreg
reti
int_timer0: ;счет таймера переполненй каждые 5,12 сек
in temp_sreg,SREG
subi delay,1
sbci delay_H,0
out SREG,temp_sreg
reti
int_timer1: ;счет таймера переполнений 164 мС
in temp_sreg,SREG
dec ms_delay
out SREG,temp_sreg
reti


