Программа для микроконтроллераВ УКОВ применяется микроконтроллер ATtiny26 фирмы ATMEL. Отладка производилась в AVR Studio. Исходный код программы приведен ниже .include "tn26def.inc" ;файл описаний имен регистров .def tmp=r16 ;рабочая переменная .def hrs=r20 ;количество часов .def num=r18 ;рабочая переменная .def m=r21 ;m=0, если задействован таймер. ;m используется для ;предотвращения режима BLINK ;в режиме "ТАЙМЕР" rjmp RESET ;переход после сброса rjmp EXT_INT0 ;переход после внешнего прерывания RESET: ;главная программа ldi tmp,RAMEND ;инициализация стека out sp,tmp ldi tmp,0b01000000 out GIMSK,tmp ;разрешаем внешнее прерывание INT0 ldi tmp,0b00000010 out MCUCR,tmp ;настроим прерывание по заднему ;фронту импульса ldi tmp,0b01111111 ;настройка портов out ddra,tmp ;РА0..РА6 - на вывод, РА7 - на ввод ldi tmp,0b00000110 ;РB4,PB6,PB5,PB3 - на ввод, out ddrb,tmp ;PB2,PB1 - на вывод clr tmp ;tmp = 0 clr hrs ;hrs = 0 rcall INDICATE START: clr tmp clr hrs rcall INDICATE sei ;разрешаем прерывания STRT: sbis pina,7 ;ждем нажантия кнопки "ПУСК" rjmp STRT rcall del_s ;задержка 1 сек rcall del_s sbis pina,7 ;если "ПУСК" всё еще нажат - работаем rjmp STRT ;иначе - ждем снова sbi portb,1 ;оповещаем rcall del_s ;пользователя cbi portb,1 ;о начале rcall del_s ;отработки sbi portb,1 ;алгоритма rcall del_s ;мерцанием cbi portb,1 ;светодиода sbis pinb,3 ;если РВ3 = 1, то идем rjmp REPEAT ;на режим "ТАЙМЕР", иначе - "ПОВТОР" rcall INDICATE TIMER: cli ;режим "ТАЙМЕР" rcall INDICATE tst hrs ;если hrs = 0, то откачиваем воду breq IMMEDIATE ;если нужно подождать, то dec hrs ;инкрементируем hrs и rcall del_h ;ждем rjmp TIMER IMMEDIATE: rcall IND_LS sbis pinb,5 rjmp START rcall PUMPING clr hrs rjmp START INDICATE: ;отображение hrs на 7-сегментнике cpi hrs,1 ;сравниваем hrs с единицей если ;hrs <> 1, то проверяем равенство brne TWO ;hrs двойке. Если же hrs = 1, то ldi num,0b00000110 ;пишем в num число, для "1" out porta,num ;и выводим на индикацию ret ;выходим из подпрограммы TWO: cpi hrs,2 brne THREE ldi num,0b01011011 out porta,num ret THREE: cpi hrs,3 brne FOUR ldi num,0b01001111 out porta,num ret FOUR: brne FIVE ldi num,0b01100110 out porta,num ret FIVE: cpi hrs,5 brne SIX ldi num,0b01101101 out porta,num ret SIX: cpi hrs,6 brne SEVEN ldi num,0b01111101 out porta,num ret SEVEN: cpi hrs,7 brne EIGHT ldi num,0b00000111 out porta,num ret EIGHT: cpi hrs,8 brne NINE ldi num,0b01111111 out porta,num ret NINE: cpi hrs,9 brne ZERO ldi num,0b01101111 out porta,num ret ZERO: ldi num,0b00111111 out porta,num ret REPEAT: cli ;режим "ПОВТОР" rcall INDICATE tst hrs breq PUMP rcall del_h dec hrs rcall INDICATE rcall REPEAT PUMP: mov hrs,tmp ;восстанавливаем данные rcall IND_LS sbis pinb,5 ;проверяем, если ДУ=0, то rjmp REPEAT rcall PUMPING rjmp REPEAT PUMPING: ;подпрограмма откачки ldi m,1 sbi portb,1 ;оповещаем пользователя sbi portb,2 ;и включяем насос CONT: com m ;задержка 1 мин с анимацией mov num,m inc num andi num,1 breq INV ldi num,0b00000001 ;горит сегмент A out porta,num rcall del_s rcall del_s ldi num,0b00000011 ;B out porta,num rcall del_s rcall del_s ldi num,0b00000111 ;C out porta,num rcall del_s rcall del_s ldi num,0b00001111 ;D out porta,num rcall del_s rcall del_s ldi num,0b00011111 ;E out porta,num rcall del_s rcall del_s ldi num,0b00111111 ;F out porta,num rcall del_s rjmp CHK INV: ldi num,0b00111110 ;горит сегмент A out porta,num rcall del_s rcall del_s ldi num,0b00111100 ;B out porta,num rcall del_s rcall del_s ldi num,0b00111000 ;C out porta,num rcall del_s rcall del_s ldi num,0b00110000 ;D out porta,num rcall del_s rcall del_s ldi num,0b00100000 ;E out porta,num rcall del_s rcall del_s ldi num,0b00000000 ;F out porta,num rcall del_s CHK: rcall del_s sbic pinb,5 ;если уровень высокий, то rjmp CONT ;продолжаем откачку ;если уровень стал низким, то cbi portb,1 ;завершаем прозвон, отключаем cbi portb,2 ;насос и сигнализацию откачки clr hrs rcall INDICATE ret ;выходим из подпрограммы IND_LS: ;оповещаем о проверке ДУ: ;два раза мерцает "d" clr num out porta,num rcall del_s ;на индикаторе 0.5 сек пусто ldi num,0b01011110 out porta,num rcall del_s ;затем 0.5 сек горит "d" clr num out porta,num rcall del_s ;снова пусто ldi num,0b01011110 out porta,num rcall del_s ;и опять "d" clr num out porta,num ;пусто ret ;выходим из подпрограммы EXT_INT0: ;отработка внешнего прерывания cpi hrs,9 ;если hrs не равно 9, то brne SKIP ;не изменяем его clr hrs ;иначе - обнуляем rjmp S SKIP: inc hrs ;hrs = hrs - 1 S: mov tmp,hrs ;tmp = hrs rcall INDICATE reti del_s: ;задержка 0.5 сек push r16 ;сохраняем push r17 ;данные push r18 ;в стеке ldi r18,65 ;внешняя петля 65 del11: ldi r17,49 ;средняя петля 49 del12: ldi r16,52 ;внутренняя петля 52 del13: dec r16 ;декрементируем brne del13 ;если 0,продолжаем среднюю dec r17 ;декрементируем brne del12 ;если 0,продолжаем внешнюю dec r18 ;декрементируем brne del11 ;ели 0,задержка окончена pop r18 ;восстанавливаем pop r17 ;данные pop r16 ;со стека ret ;выходим в осно. прогу del_h: ;подпрограмма задержки 1 час push r16 ;сохраняем push r17 ;данные push r18 ;в стеке push r19 ldi r19,246 ;246 (109 для 5 сек) del34: ldi r18,140 ;140 (150 для 5 сек) del33: ldi r17,180 ;180 (10 для 5 сек) del32: ldi r16,195 ;195 (10 для 5 сек) del31: dec r16 brne del31 dec r17 brne del32 dec r18 brne del33 dec r19 brne del34 pop r19 pop r18 ;восстанавливаем pop r17 ;данные pop r16 ;со стека ret © 2010 Логинов Вадим |