.org 0x000 rjmp init ;прерывание происходит при сбрасывании RESET .org 0x012 rjmp timer_0;при переполнении счетчика таймера ;попадаем в подпрограмму обработки
;**************************************************** ;*** прерывание по переполнению таймера/счетчика0 *** ;**************************************************** ;мы сюда попадаем, когда в счетном регистре значение превысит ;255. Данная подпрограмма выполняется одновременно с ;основной программой, здесь мы устанавливаем флаг. ;в основной программе необходимо проверять этот флаг ;и как только он установится выполнить нужную инструкцию ;**************************************************** timer_0: ; push temp ;помещение содержимого регистра в стек ldi temp,0x00 ;остановка счетчика out TCCR0,temp ; SET ;установка флага T в регисте SREG pop temp ;извлечение из стека в регистр reti ;Возврат из прерывания ;****************************************************
;******************************************************** ;настройка портов ввода/вывода - это можно сравнить ;с объявлением необходимых переменных ;******************************************************** ldi temp,0b11111111 ;настройка порта B 1-выход 0-вход out DDRB,temp ldi temp,0b00000000 ;настройка порта B out PORTB,temp
ldi temp,0b11111111 ;настройка порта C 1-выход 0-вход out DDRC,temp ldi temp,0b00000000 ;настройка порта C out PORTC,temp
ldi temp,0b11111111 ;настройка порта D 1-выход 0-вход out DDRD,temp ldi temp,0b00000000 ;настройка порта D out PORTD,temp
ldi temp,0x04 ;***************** out sph,temp ;*** Настройка *** ldi temp,0x5f ;*** стека *** out spl,temp ;***************** ;********************************************************
;******************* настройка таймера/счетчика 0 ldi temp,0b00000001 ;Разрешаем прерывание out TIMSK,temp ;установкой "1" в разряда TOIE0 SEI ;Общее разрешение прерываний
rjmp Main ;так создается бесконечный цикл ;********************************************************
;*************** ;*** LED ten *** ;*************** led_10: push temp ;помещение содержимого регистра в стек push temp1 ;чтоб не изменить значения переменных push temp2 ;в главной программе ldi temp2,10 ;задаем количество циклов
time_1sec: in temp1,PORTD ;узнаем какие биты включены у порта D ldi temp,0x1 ;записываем в нулевой бит регистра единицу eor temp,temp1 ;исключающее или между регистрами ;т.е. если было 1 станет 0 и наоборот out PORTD,temp ;записываем в порт D полученное значение rcall timer_100 ;вызов задержки на 0,1 секунды dec temp2 ;уменьшаем значение temp2 на 1 tst temp2 ;проверка на ноль breq time_1sec_end;и если ноль выходим из цикла rjmp time_1sec ;иначе повторяем цикл
time_1sec_end: pop temp2 ;извлечение из стека в регистр pop temp1 ;возвращаем переменным значение, которое pop temp ;было до попадания в подпрограмму ret ;возврат из подпрограммы ;******************* ;*** end LED ten *** ;*******************
;************************************************************ ;*** Подпрограмма отсчета времени 100 мс на 8МГц ************ ;*** при помощи внутреннего таймера/счетчика 0 ************ ;************************************************************ timer_100: push temp ;помещение содержимого регистра в стек
ldi temp,0b00000000 ;обнуляем счетчик out TCNT0,temp ; ldi temp,0b00000101 ;запускаем счетчик out TCCR0,temp ;в режиме деления на 1024
;в режиме деления на 1024 - это означает, что счетный регистр ;увеличивается на единицу не каждый такт, а каждый 1024 такт ;для того чтоб регистр переполнился необходимо ;255*1024= 261120 тактов, а для достижения задержки 0,1 сек ;необходимо 800000 тактов, если мы повторим переполнение ;счетного регистра 3 раза получим 783360 тактов ;т.к. ракеты в космос мы не отправляем, приблизительно ;у нас получилось 0,09792сек - округлим как 0,1сек
timer_100_1: brts timer_100_1end ;переход, если флаг T установлен rjmp timer_100_1 ;
timer_100_1end: ; CLT ;Сброс флага T в регисте SREG ldi temp,0b00000000 ;обнуляем счетчик out TCNT0,temp ; ldi temp,0b00000101 ;запускаем счетчик out TCCR0,temp ;в режиме деления на 1024 rjmp timer_100_2 ;
timer_100_2: brts timer_100_2end ;переход, если флаг T установлен rjmp timer_100_2 ;
timer_100_2end: ; CLT ;Сброс флага T в регисте SREG ldi temp,0b00000000 ;обнуляем счетчик out TCNT0,temp ; ldi temp,0b00000101 ;запускаем счетчик out TCCR0,temp ;в режиме деления на 1024 rjmp timer_100_3 ;
timer_100_3: brts timer_100_3end ;переход, если флаг T установлен rjmp timer_100_3 ;
timer_100_3end: ; CLT ;Сброс флага T в регисте SREG pop temp ;извлечение из стека в регистр ret ;возврат из подпрограммы ;************************************************************* ;*** Окончание подпрограммы отсчета времени 100 мс на 8МГц *** ;*************************************************************
;********************************************************* ;*** Подпрограмма отсчета времени 1c на 8МГц ************* ;********************************************************* time_1s: push temp push temp1 push temp2
;регистры размером 8бит, т.е. 2 в 8-й степени = 256 ;т.к. счет идет с нуля значит максимальное число 255 ;внутренний цикл состоит из команд, которые выполняются ;в течении 5-ти циклов, 1 цикл = 1/частоту кварца ;1/8'000'000=0,000'000'125 - это длительность с секундах ;одного цикла. Умножаем на 5, внутренний цикл повторяется ;254 раза, средний - 200 и самый верхний 32, получаем ;0,000'000'125*5*254*200*32=1,016секунды - вот так ;делаем задержку при тактировании от внешнего кварца
time_1s_1: dec temp ;********************************* tst temp ;*** внутреннее тело цикла 5кц *** breq time_1s_2 ;********************************* rjmp time_1s_1 ;*********************************
time_1s_2: dec temp1 tst temp1 breq time_1s_3 rjmp time_1s_01
time_1s_3: dec temp2 tst temp2 breq time_1s_end rjmp time_1s_001
time_1s_end:pop temp2 pop temp1 pop temp ret ;********************************************************* ;*** Окончание подпрограммы отсчета времени 1с на 8МГц *** ;*********************************************************