Не хотел нагружать вас, думал есть какие-то классические грабли
Вот весь код (я только учусь, так что на стиль прошу не обращать внимания - проблема лишь с перезагрузкой
):
Код:
.include "m8def.inc" ; подключаем заголовочный файл для ATmega8L-8PU, (ATmega8L-8PI), PbFree PDIP28
.def Temp=R16 ; разное
.def module_1_full=R17 ; Увлажнитель
.def module_2_full=R18 ; Мойщик
.def module_3_full=R19 ; Полив
.def module_3_in_progress=R20 ; Процесс полива
.def SubSecondCount=R21 ; расширитель таймера
.def Sek=R22 ; Cекунды
.def Min=R23 ; Минуты
.def Hour=R24 ; Часы
.def Module_3_was_off=R25 ; Модуль №3 был выключен кнопкой
.cseg ; начало программного сегмента
.org 0 ; задает начальный адрес. В данном случае он = 0
;************_ НОЖКИ _************
;PB0 - Помпа / насос
;PB1 - клапан №1
;PB2 - клапан №2
;PB3 - клапан №3
;PB4 - светодиод протечек
;PB5 -
;PB6 -
;PB7 -
;PD0 - протечка №1 / Alarm_Main
;PD1 - протечка №2 / Alarm_2
;PD2 - кнопка вкл/выкл модуля №1
;PD3 - кнопка вкл/выкл модуля №2
;PD4 - кнопка вкл/выкл модуля №3
;PD5 - кнопка вкл/выкл Принуждителя модуля №1
;PD6 - кнопка вкл/выкл Принуждителя модуля №2
;PD7 - кнопка вкл/выкл Принуждителя модуля №3
;PC0 - верхний датчик модуля №1
;PC1 - нижний датчик модуля №1
;PC2 - верхний датчик модуля №2
;PC3 - нижний датчик модуля №2
;PC4 -
;PC5 -
;PC6 -
;************_ НАСТРОЙКА ПРЕРЫВАНИЙ _************
rjmp Reset
nop
nop
nop
nop
nop
nop
nop
nop
rjmp TIMER0_OVF
;************_ ПРОЧИЕ НАСТРОЙКИ _************
RESET:
ldi Temp, low(RAMEND) ; инициализация стека
out SPL, Temp ; инициализация стека
ldi Temp, high(RAMEND) ; инициализация стека
out SPH, Temp ; инициализация стека
ldi Temp, 0xBF ; калибровка частоты внутреннего генератора на 8 мГЦ
out osccal, Temp
ldi Temp,0b00011111 ; определение ножек МК портов B (1 = вывод | 0 = ввод). Порты B относятся к Питанию помпы, клапанам и светодиоду протечек
out DDRB,Temp ; настраивает ножки МК портов B в соответствии с данными выше
ldi Temp,0b00011111 ; подаём напряение на определённые порты/ножеки, чтобы потом оно было нормальным, не тусклым
out PortB,Temp
ldi Temp,0b00000000 ; определение ножек МК портов D (1 = вывод | 0 = ввод). Порты D относятся к Проверке протечек и кнопкам
out DDRD,Temp ; настраивает ножки МК портов D в соответствии с данными выше
ldi Temp,0b00000000 ; подаём напряение на определённые порты/ножки
out PortD,Temp
ldi Temp,0b0000000 ; определение ножек МК портов C (1 = вывод | 0 = ввод). Порты C относятся к Датчикам
out DDRC,Temp ; настраивает ножки МК портов C в соответствии с данными выше
ldi Temp,0b0000000 ; подаём напряение на определённые порты/ножки
out PortC,Temp
ldi Temp,4 ; предделитель считает каждый 256 импульс
out TCCR0,Temp ; то есть при тактовой частоте 8 Мгц прерывания будут происходить каждые 8192 мкс
; в одной секунде таких кусочков 122, а значит в регистр расширитель надо записать число 256-122=134
ldi SubSecondCount, 134 ;
ldi Temp,0b00000001 ; разрешение прерываний Переполнения Таймера 0
out TIMSK,Temp ;
sei ; разрешить Прерывания
clr Sek ; обнуляем Секунды
clr Min ; обнуляем Минуты
clr Hour ; обнуляем Часы
ldi Module_3_was_off,0 ; Модуль №3 ещё кнопкой Не выключался
ldi module_3_in_progress,0 ; завершить Процесс полива
;************_ ЧТОБЫ НОЖКИ НОРМАЛЬНО ОБЕСПЕЧИВАЛИСЬ ТОКОМ, а не "тускло" _************
; cbi PORTB, PB0
; cbi PORTB, PB1
; cbi PORTB, PB2
; cbi PORTB, PB3
cbi PORTB, PB4
;************_ ФЛАГИ И ПРОВЕРКИ _************
sbi PORTB, PB4 ; зажечь светодиод протечек
Wait_1: cpi Sek, 1 ; секунды равны 1?
brne Wait_1 ; пока нет
CBI PORTB, PB4 ; да, погасить светодиод протечек
Begin: sbis PIND,0 ; проверка есть ли протечка №1 (получаем данные с ножки PD0 и сравнение/сама проверка)
rcall Alarm_Main ; есть замыкание / протечка №1
sbic PIND,2 ; нет замыкания / проверка вЫключен ли модуль №1 (получаем данные с ножки PD2 и сравнение/сама проверка)
ldi module_1_full,1 ; нет замыкания / вЫключен - вЫключить модуль №1
sbic PIND,2 ; есть замыкание / проверка вЫключен ли модуль №1 (получаем данные с ножки PD2 и сравнение/сама проверка)
rjmp Alarm_2 ; нет замыкания / вЫключен - перейти к Проверке протечки №2
sbis PIND,5 ; есть замыкание / проверка включоно ли Принуждение модуля №1 (получаем данные с ножки PD5 и сравнение/сама проверка)
ldi module_1_full,0 ; есть замыкание / включено - включить модуль №1
sbis PIND,5 ; нет замыкания / проверка включоно ли Принуждение модуля №1 (получаем данные с ножки PD5 и сравнение/сама проверка)
rjmp Alarm_2 ; есть замыкание / включено - перейти к Проверке протечки №2
rcall Module_1_full_Check ; нет замыкания / проверка пуст или полон модуль №1
Alarm_2: sbis PIND,1 ; проверка есть ли протечка №2 (получаем данные с ножки PD1 и сравнение/сама проверка)
rcall Alarm_2_yes ; есть замыкание / протечка №2
CBI PORTB, PB4 ; нет замыкания / погасить светодиод протечек
Alarm_2_end: sbic PIND,3 ; нет замыкания / проверка вЫключен ли модуль №2 (получаем данные с ножки PD3 и сравнение/сама проверка)
ldi module_2_full,1 ; нет замыкания / вЫключен - вЫключить модуль №2
sbic PIND,3 ; есть замыкание / проверка вЫключен ли модуль №2 (получаем данные с ножки PD3 и сравнение/сама проверка)
rjmp Module_3 ; нет замыкания / вЫключен - перейти к Модулю №3
sbis PIND,6 ; есть замыкание / проверка включоно ли Принуждение модуля №2 (получаем данные с ножки PD6 и сравнение/сама проверка)
ldi module_2_full,0 ; есть замыкание / включено - включить модуль №2
sbis PIND,6 ; нет замыкания / проверка включоно ли Принуждение модуля №2 (получаем данные с ножки PD6 и сравнение/сама проверка)
rjmp Module_3 ; есть замыкание / включено - перейти к Модулю №3
rcall Module_2_full_Check ; нет замыкания / проверка пуст или полон модуль №2
Module_3: sbic PIND,4 ; нет замыкания / проверка вЫключен ли модуль №3 (получаем данные с ножки PD4 и сравнение/сама проверка)
rcall Module_3_Off ; нет замыкания / вЫключен - вЫключить модуль №3 и Запомнить, что модуль №3 был выключен кнопкой
sbic PIND,4 ; есть замыкание / проверка вЫключен ли модуль №3 (получаем данные с ножки PD4 и сравнение/сама проверка)
rjmp Management ; нет замыкания / вЫключен - перейти к ***_Управлению_***
sbis PIND,7 ; есть замыкание / проверка включоно ли Принуждение модуля №3 (получаем данные с ножки PD7 и сравнение/сама проверка)
ldi module_3_full,0 ; есть замыкание / включено - включить модуль №3
sbis PIND,7 ; нет замыкания / проверка включоно ли Принуждение модуля №3 (получаем данные с ножки PD7 и сравнение/сама проверка)
rjmp Management ; есть замыкание / включено - перейти к ***_Управлению_***
CPI module_3_in_progress,1 ; нет замыкания / проверка идёт ли Процесс полива модуля №3
breq In_progress_module_3 ; есть замыкание
cpi Module_3_was_off,1 ; проверить вЫключался ли Модуль №3 кнопкой
BRNE Mudule_3_Go_On
clr Sek ; обнуляем Секунды
clr Min ; обнуляем Минуты
clr Hour ; обнуляем Часы
ldi Module_3_was_off,0 ; обнуляем память, что Модуль №3 был вЫключен кнопкой
; __ Сутки (24 часа и одна секунда) прошли? __
Mudule_3_Go_On: cpi Hour, 0
BRNE Management ; ещё нет / не равно / перейти к ***_Управлению_**
cpi Min, 0
BRNE Management ; ещё нет / не равно / перейти к ***_Управлению_**
cpi Sek, 1
BRNE Management ; ещё нет / не равно / перейти к ***_Управлению_**
ldi module_3_full,0 ; да, Сутки Прошли / равно / включить модуль №3
ldi module_3_in_progress,1 ; активировать Процесс полива
rjmp Management ; перейти к ***_Управлению_**
In_progress_module_3: cpi Sek, 10 ; Сколько Секунд Поливать
BRLO Management ; время полива ещё не прошло
ldi module_3_full,1 ; время полива прошло - вЫключить модуль №3
ldi module_3_in_progress,0 ; завершить Процесс полива
;************_ УПРАВЛЕНИЕ _************
Management: ldi Temp,0
CPSE Temp, module_1_full
rcall Module_1_full_set_Close
rcall Module_1_full_set_Open
Next_2: CPSE Temp, module_2_full
rcall Module_2_full_set_Close
rcall Module_2_full_set_Open
Next_3: CPSE Temp, module_3_full
rcall Module_3_full_set_Close ; иначе закрыть клапан №3
rcall Module_3_full_set_Open
Next_4: CPSE Temp, module_1_full
rjmp Begin ; если не равно
CPSE Temp, module_2_full ; если равно
rjmp Begin ; если не равно
CPSE Temp, module_3_full ; если равно
rjmp Begin ; если не равно
sbi PORTB, PB0 ; вЫключить помпу / если равно
rjmp Begin
;************_ ПОДПРОГРАММЫ _************
Alarm_Main: CBI PORTB, PB0 ; выключаем помпу
CBI PORTB, PB1 ; закрываем клапан №1
CBI PORTB, PB2 ; закрываем клапан №2
CBI PORTB, PB3 ; закрываем клапан №3
sbi PORTB, PB4 ; зажечь светодиод протечек
Block: sbis PIND,0 ; проверка есть ли протечка №1 (получаем данные с ножки PD0 и сравнение/сама проверка)
rjmp Block ; есть замыкание / протечка №1
CBI PORTB, PB4 ; погасить светодиод протечек
ret
Module_1_full_Check: sbis PINC,0 ; замкнут ли Верхний датчик модуля №1 (получаем данные с ножки PC0 и сравнение/сама проверка)
rjmp Module_1_full_Check_2 ; есть замыкание / модуль полный
sbis PINC,1 ; нет замыкания / замкнут ли Нижний датчик модуля №1 (получаем данные с ножки PC1 и сравнение/сама проверка)
rjmp Module_1_full_Check_2 ; есть замыкание / модуль недостаточно пуст, чтобы в его доливать
ldi module_1_full,0 ; нет замыкания / модуль пустой
rjmp Module_1_full_Check_exit
Module_1_full_Check_2: ldi module_1_full,1
Module_1_full_Check_exit: ret
Alarm_2_yes: ldi module_1_full,1
sbi PORTB, PB4 ; зажечь светодиод протечек
rjmp Alarm_2_end
ret
Module_2_full_Check: sbis PINC,2 ; замкнут ли Верхний датчик модуля №2 (получаем данные с ножки PC2 и сравнение/сама проверка)
rjmp Module_2_full_Check_2 ; есть замыкание / модуль полный
sbis PINC,3 ; нет замыкания / замкнут ли Нижний датчик модуля №2 (получаем данные с ножки PC3 и сравнение/сама проверка)
rjmp Module_2_full_Check_2 ; есть замыкание / модуль недостаточно пуст, чтобы в его доливать
ldi module_2_full,0 ; нет замыкания / модуль пустой
rjmp Module_2_full_Check_exit
Module_2_full_Check_2: ldi module_2_full,1
Module_2_full_Check_exit: ret
Module_3_Off: ldi module_3_full,1 ; вЫключить модуль №3
ldi Module_3_was_off,1 ; Запомнить, что модуль №3 был выключен кнопкой
ret
Module_1_full_set_Open: sbi PORTB, PB1 ; открыть клапан №1
sbi PORTB, PB0 ; включить помпу
ret
Module_1_full_set_Close: CBI PORTB, PB1 ; закрыть клапан №1
rjmp Next_2
ret
Module_2_full_set_Open: sbi PORTB, PB2 ; открыть клапан №2
sbi PORTB, PB0 ; включить помпу
ret
Module_2_full_set_Close: CBI PORTB, PB2 ; закрыть клапан №2
rjmp Next_3
ret
Module_3_full_set_Open: sbi PORTB, PB3 ; открыть клапан №3
sbi PORTB, PB0 ; включить помпу
ret
Module_3_full_set_Close: CBI PORTB, PB3 ; закрыть клапан №3
rjmp Next_4
ret
;************_ ОБРАБОТЧИК ПРЕРЫВАНИЯ Timer0 overflow _************
TIMER0_OVF:
push Temp ; сохранили регистр в стеке
push r15 ; сохранили регистр в стеке
in r15, $3f ; сохранили статус регистр
inc SubSecondCount ; инкремент регистра расширителя
cpi SubSecondCount, 0
brne end ; переход, если не было переполнения
; регистр расширитель досчитал до переполнения, то есть секунда прошла
ldi SubSecondCount, 134 ; перезагрузка расширителя
inc Sek ; инкремент секунд
cpi Sek, 60 ; проверка переполнения
brne end ; нет переполнения - выход
clr Sek ; иначе обнуляем секунды
inc Min ; и инкрементируем минуты
cpi Min, 60 ; проверка переполнения
brne end ; нет переполнения - выход
clr Min ; иначе обнуляем минуты
inc Hour ; и инкрементируем часы
cpi Hour, 24 ; проверка переполнения
brne end ; нет переполнения - выход
clr Hour ; иначе обнуляем часы (при этом как раз сутки и прошли)
;
;ldi Temp, 1
;eor Led, Temp ; если флаг был нулем - он станет единицей (НУЖНО ОПРЕДЕЛИТЬ РЕГИСТР "LED")
; если флаг был единицей - он станет нулем
; делаем зачистку за собой
end: out $3f, r15 ; восстановили статус регистр
pop r15 ;
pop Temp ;
reti ;