Ответ в теме: Программирование МК AVR



#22392
oleg5672
Участник

Здравствуйте друзья нужна помощь подправить код ИК-приёмник на Attiny13. При долговременном нажатии на кнопку пульта светодиод на выходе работает в тригерном режиме , надо поправить код чтоб светодиод при долговременном(удержание кнопки пульта) нажатии на кнопку пульта горел постоянно . Ниже прилагаю код написанный на assembler
;— http://radiohlam.ru — собери сам, помоги собрать другу
;——————————————————————
.device ATtiny13
.include «tn13def.inc»
.list

;— определ¤ем свои переменные
.def w=r16 ; это будет наш аккумул¤тор
.def MBC=r17 ; старший байт посылки
.def LBC=r18 ; младший байт посылки
.def Sch=r19 ; счЄтчик прин¤тых бит
.def C_time=r20; текущее значение таймера
.def H_time=r21; 3/4 бита
;— определ¤ем константы
.equ Sys=29 ; номер системы
.equ CMD_1=1 ; 000001 код команды=1
.equ CMD_2=2 ; 000010 код команды=2
.equ CMD_3=3 ; 000011 код команды=3
.equ CMD_4=4 ; 000100 код команды=4
.equ Delay = 100
;— »спользуемые регистры
; SPL — указатель вершины стека
; ACSR — управление компаратором
; DDRB — направление работы ног
; PORTB — выходы порта
; PCMSK — разрешение прерываний на отдельных входах
; GIMSK — общее разрешение прерываний по входам
; GTCCR — сброс предделител¤
; TCCR0B — управление таймером
; TIMSK0 — прерывани¤ от таймера
; PB0 — выход D3, PB1- выход D2, PB2- выход D1, PB3 — вход, PB4 — выход D4
;— начало программного кода
.cseg
.org 0
rjmp Init ; переход на начало программы
;— вектора прерываний
reti ; INT0
rjmp Pch ; Pin Change
rjmp Timer ; Timer
reti ; EEPROM
reti ; comparator
reti ; timer compare match A
reti ; timer compare match B
reti ; watchdog
reti ; ADC
;— начало программы
Init: ldi w,RAMEND ; устанавливаем указатель вершины
out SPL,w ; стека на старший байт RAM
sbi ACSR,7 ; выключаем компаратор
ldi w,0b00010111 ; определ¤ем входы и выходы порта
out DDRB,w
ldi w,0b11101000 ; включаем подт¤гивающие резисторы
out PORTB,w ; и определ¤ем начальное состо¤ние выходов
;— разрешить прерывани¤ от таймера (пока он не запущен — прерывани¤ всЄ равно не будет)
ldi w,0b00000010
out TIMSK0,w ; разрешить прерывани¤ от таймера
;— ќбнул¤ем счЄтчик и регистр флагов
Reset: in w,PORTB ; читаем порт
clr Sch
clt ; сбрасываем флаг “
;— разрешить прерывание от входов
ldi w,0b00100000
out GIMSK,w ; разрешаем прерывание от входов
;— разрешить прерывани¤ на входе PB3
Start: ldi w,0b00100000
out GIFR,w ; сбросить флаг прерываний от входов
ldi w,0b00001000
out PCMSK,w ; разрешаем прерывани¤ на входе PB3
sei ; разрешить глобальные прерывани¤
Scan: nop
rjmp Scan
;— ќЅ–јЅќ“„»  ѕ–?–џ¬јЌ»я ѕќ ¬’ќ?”
;— инициализируем счЄтчик, адр.бита, пров.рег., адр.рег.записи
Pch: tst Sch ; счЄтчик =0?
brne Next
Nachalo: sbic PINB,3 ; если на входе низкий уровень — пропускаем команду
reti ; это не приЄм — выходим
ldi w,0b00000001
out GTCCR,w ; сбросить предделитель
ldi w,0b00000100
out TCCR0B,w ; запустить таймер с делителем на 256
sec ; подн¤ть carry flag
rol LBC
rol MBC
inc Sch
reti
Next: in C_time,TCNT0 ; читаем значение таймера
clr w
out TCNT0,w ; перезапускаем таймер
cpi Sch,1 ; Sch=1?
brne Next2
Next1: mov H_time,C_time
lsr C_time ; находим четверть бита
add H_time,C_time ; находим 3/4 бита
set ; ставим флаг пропуска (T в регистре SREG)
sec
rol LBC
rol MBC
inc Sch ; увеличиваем счЄтчик
reti
Next2: brts Not_Signed_FRont
Signed_Front:
cp C_time,H_time
brsh Long_time
Short_time: set ; установить признак пропуска
clc
sbrc LBC,0 ; пропустить, если прошлоне значение = 0
sec
rjmp Zapis_bita
Long_time: clc ; принимаемый бит инвертирован, по отношению к последнему
sbrs LBC,0 ; пропустить, если прошлое значение = 1
sec
Zapis_bita: rol LBC
rol MBC
inc Sch
cpi Sch,14
breq rab_chast
reti
Not_Signed_Front:
clt
reti
;— ќЅ–јЅќ“„»  ѕ–?–џ¬јЌ»я ќ“ “ј…ћ?–ј
Timer: clr w
out TCCR0B,w ; выключить таймер
pop w ; очищаем стек
pop w
rjmp Reset ; ресетимс¤

;— –јЅќ„јя „ј—“№
;— ѕроверка номера системы и команды
rab_chast: clr w
out TCCR0B,w ; выключить таймер
out TCNT0,w ; сбросить таймер
pop w ; очищаем стек
pop w
clc
rol LBC ; сдвигаем всЄ, кроме номера команды в MBC
rol MBC
clc
rol LBC
rol MBC
lsr LBC ; выравниваем номер команды младшим битом к
lsr LBC ; младшему биту байта
in w,PORTB ; читаем порт B
cpi LBC,CMD_1
breq Button1
cpi LBC,CMD_2
breq Button2
cpi LBC,CMD_3
breq Button3
cpi LBC,CMD_4
breq Button4
rjmp Reset
Button1: ldi Sch,0b00000001
eor w,Sch ; инвертируем нулевой бит
out PORTB,w
rjmp Thats_all
Button2: ldi Sch,0b00000010
eor w,Sch ; инвертируем первый бит
out PORTB,w
rjmp Thats_all
Button3: ldi Sch,0b00000100
eor w,Sch ; инвертируем второй бит
out PORTB,w
rjmp Thats_all
Button4: ldi Sch,0b00010000
eor w,Sch ; инвертируем четвЄртый бит
out PORTB,w
Thats_all: rcall Pause
rjmp Reset
Pause: ldi R22, Delay ; загрузка константы для задержки в регистр R22
WLoop0:
ldi R23, 0x28 ; загружаем число 40 (0x28) в регистр R23
WLoop1:
ldi R24, 0xFF ; загружаем число 255 (0xFF) в регистр R24
WLoop2:
dec R24 ; уменьшаем значение в регистре R24 на 1
brne WLoop2 ; возврат к WLoop2 если значение в R24 не равно 0
dec R23 ; уменьшаем значение в регистре R23 на 1
brne WLoop1 ; возврат к WLoop1 если значение в R23 не равно 0
dec R22 ; уменьшаем значение в регистре R22 на 1
brne WLoop0 ; возврат к WLoop0 если значение в R22 не равно 0
eor w,Sch ; инвертируем второй бит
out PORTB,w
ret ; возврат из подпрограммы Pause