Код: Выделить всё
; ******************************************************
; * Автор: СКАЗОЧНИК *
; * Дата: 10.10.2014 *
; * Версия: 140831 *
; * Имя файла: ИК управление *
; * Для AVR: ATTiny13 *
; * Тактовая частота: 9,6 MHz *
; * Среда разработки: AVR Studio 4.12 *
; * *
; * Выполняемые функции: *
; * *
; * *
; ******************************************************
; ================
; ПОДКЛЮЧАЕМЫЕ БИБЛИОТЕКИ (.include)
; ================
.include "tn13def.inc"
; ============
; ТИП МИКРОКОНТРОЛЛЕРА (.device)
; ============
.device ATtiny13
; =================
; ОБЪЯВЛЕНИЯ И КОНСТАНТЫ (.def, .equ)
; =================
.def temp = R16
.def TIME = R17
.def FLAG = R18
.def LADR = R19
.def HADR = R20
.def LCMD = R21
.def HCMD = R22
.def CNT = R23
.def RUN = R24
.def SCREEN = R25
.def YYY = R26
; ====
; МАССИВЫ И Т.Д. (.eseg) EEPROM (.db, .dw)
; ====
.eseg
; =================
; МАКРОСЫ (.MACRO)
; =================
.MACRO PUSHF ; Положить СРЕГ в стек
push r16
in r16, SREG
push r16
.ENDM
.MACRO POPF ; Достать СРЕГ из стека
pop r16
out SREG, r16
pop r16
.ENDM
; ******************************
; НАЧАЛО ПРОГРАММЫ (.cseg) FLASH
; ******************************
.cseg
; ----------
; ВЕКТОРЫ ПРЕРЫВАНИЙ
; ----------
rjmp RESET ; Reset Handler
rjmp INT0add ; External Interrupt0 Handler
rjmp PCI0add
rjmp OVF0add
rjmp ERDYadd
rjmp ACIadd
rjmp OC0Aadd
rjmp OC0Badd
rjmp WDTadd
rjmp ADCCadd
;RESET: ; Reset Handler
;INT0add: ; External Interrupt0 Handler
PCI0add:
OVF0add:
ERDYadd:
ACIadd:
OC0Aadd:
OC0Badd:
WDTadd:
ADCCadd:
reti ; Выход из прерываний, которые не используются
; ----------
; ОБРАБОТЧИКИ ПРЕРЫВАНИЙ
; ----------
INT0add:
PUSHF
in TIME, TCNT0 ; Закидываем в Тайм значение счетчика, будем использовать его позже
clr temp
out TCNT0, temp ; Первоначально очищаем счетный регистр раймера
inc CNT
ldi YYY, 1
POPF
reti ; Выходим из прерывания
; OVF0add:
; inc CNT
; reti
; **************************************************************************************************
; ИНИЦИАЛИЗАЦИЯ МК (логическое начало основной программы) ******************************************
; **************************************************************************************************
; --------- конфигурация портов ----------
Reset: ldi temp, (1<<PB4)|(1<<PB3)|(0<<PB2)|(0<<PB1)|(0<<PB0) ; Конфигурация порта
out DDRB, temp
ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)
out PORTB, temp
ldi temp, (1<<INT0) ; Разрешить прерывание
out GIMSK, temp
ldi temp, (1<<ISC01)|(0<<ISC00) ; Настраиваем прерывание по низкому уровню (на ИНТ0)
out MCUCR, temp
ldi temp, low(RAMEND) ; Загрузка указателя стека
out SPL, temp
ldi temp, 0x00 ; Конфигурация таймера
out TCCR0A, temp
ldi temp, (1<<CS02)|(0<<CS01)|(1<<CS00) ; Тактовый сигнал = CK/1024 (ЗАПУСКАЕМ ТАЙМЕР)
out TCCR0B, temp
clr FLAG ; Просто очищаем
clr TIME
clr CNT
clr RUN
clr SCREEN
clr YYY
; ---------- разрешение прерываний ----------
sei ; Разрешаем прерывания
; *******************************************************************************************************************
; ОСНОВНАЯ ПРОГРАММА (основной цикл) ********************************************************************************
; *******************************************************************************************************************
Start:
cpi YYY, 1
brbs SREG_Z, KOD
rjmp Start
KOD: rcall NULONE
cpi RUN, 1
brbs SREG_Z, KOD1
rjmp Start
KOD1: rcall DRIWER
rjmp Start ; Конец программы, переход на начало
; *******************************************************************************************************************
; ПОДПРОГРАММЫ ******************************************************************************************************
; *******************************************************************************************************************
NULONE: ; Заполнение 4 переменных нулями и единицами с послыл
cpi FLAG, 0
brbc SREG_Z, A1 ;
inc FLAG
clr YYY
ret
A1: cpi FLAG, 1
brbc SREG_Z, A2
cpi TIME, 120 ; Проверка 122 < T < 130
brlo END
cpi TIME, 132
brsh END
N: ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(0<<PB1)|(1<<PB0) ; Стоп мотор
out PORTB, temp
rjmp N
inc FLAG
clr CNT
clr YYY
ret
A2: cpi FLAG, 2
brbc SREG_Z, END
cpi TIME, 8 ; Проверка 8 < T < 12
brbs SREG_C, END
cpi TIME, 12
brbc SREG_C, ONE
clc ; Убираем флаг С
rol LCMD ; Задвигаем ноль в самый правый разряд
rol HCMD ; и по очереди сдвигаем все байты влево
rol LADR ; В итогде, вся цепочка переместилась влево на один бит, а старший вывалился...
rol HADR
rjmp TT ; Все, вышли .
ONE: cpi TIME, 18 ; Проверка 18 < T < 22
brbs SREG_C, END
cpi TIME, 22
brbc SREG_C, END
sec ;
rol LCMD ;
rol HCMD ;
rol LADR ;
rol HADR
TT: cpi CNT, 32
brbs SREG_Z, PROVERKA
clr YYY
ret
PROVERKA: cpi HADR, 0b00010000
brbc SREG_Z, END
cpi LADR, 0b11001000
brbc SREG_Z, END
cpi HCMD, 0b11100001
brbc SREG_Z, END
cpi LCMD, 0b00011110
brbc SREG_Z, END
clr FLAG
clr CNT
clr YYY
ldi RUN, 1
ret
END:
clr FLAG
clr CNT
clr YYY
clr RUN
ret
; =============
DRIWER:
clr temp ; Запретить прерывание
out GIMSK, temp
cpi SCREEN, 0b00000000 ; Проверяем флаг, опущен экран или поднят
brbc SREG_Z, UP
ldi temp, (0<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0) ; Запускаем мотор вниз, а на остальных оставляем поддтяжку
out PORTB, temp
TUDA: ldi temp, (1<<TOIE0) ; Разрешить прерывание по переполнению таймера
out TIMSK0, temp
clr temp
out TCNT0, temp ; счетный регистр раймера
; ldi temp, (1<<CS02)|(0<<CS01)|(1<<CS00) ; Тактовый сигнал = CK/1024 (ЗАПУСКАЕМ ТАЙМЕР)
; out TCCR0B, temp
NEXT: cpi CNT, 2 ; ждем, пока таймер проткает 3 раза примерно 100 мсек
brbc SREG_Z, NEXT ; Тупо задержка по таймеру
clr temp ;Запретить прерывание по переполнению таймера
out TIMSK0, temp
out TCCR0B, temp
NEXT1: sbic PINB, 0 ; Пропускаем следующую, если бит очищен (датчик сработал, прижал вывод к земле)
rjmp NEXT1 ; а если не очищен, то продолажем крутиться и ждать, пока датчик не сработает
ldi temp, (0<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0) ; Стоп мотор
out PORTB, temp
com SCREEN ; переворачиваем флаг положения экрана
rjmp EX ; Выходим
UP: ldi temp, (1<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0) ; Запускаем мотор вверх
out PORTB, temp
rjmp TUDA
EX:
clr FLAG ; Просто очищаем
clr TIME
clr CNT
clr RUN
clr YYY
ldi temp, (1<<INT0) ; Разрешить прерывание
out GIMSK, temp
ldi temp, (1<<ISC01)|(0<<ISC00) ; Настраиваем прерывание по низкому уровню (на ИНТ0)
out MCUCR, temp
ret