Witam,
Zrobilem sobie prosty uklad na at90s2323. Schemat ponizej.
Kod aplikacji bazuje na przykladzie atmela AVR410.asm
Oto i sam kod.
Problem polega na tym, ze uklad "nie zawsze dziala". Czasami wlacza / wylacza sie bez problemu innym razem musze kilkakrtonie nacisnac przycisk pilota, aby spowodowac zalaczenie / wylaczenie urzadzenia.
Czy ktos moglby mnie naprowadzic na wlasciwy kierunek?
Pozdrawiam
Zrobilem sobie prosty uklad na at90s2323. Schemat ponizej.
Kod aplikacji bazuje na przykladzie atmela AVR410.asm
Oto i sam kod.
;***************************************************************************
;
; IR-Switch
;
; AT90S2323 at 4 MHz with external oscillator
;
; RC5 code is based on Atmel's Application note AVR410.asm file.
;
;***************************************************************************
.include "2323def.inc"
.equ POWER =0 ;PB0 is connected the transistor, to power-On/Off relay
.equ INPUT =1 ;PB1 is connected the TSOP1736 Infrared Receiver IC.
.equ SW =2 ;PB2 is switch
.equ SYS_ADDR =0 ;The system address - Philips TV set
.equ on_key =7 ;key 7 - device ON
.equ off_key =9 ;key 9 - device OFF
.def S =R0
.def inttemp =R18
.def ref1 =R2
.def ref2 =R3
.def temp =R16
.def temp2 =R26
.def timerL =R17
.def timerH =R16
.def system =R19
.def command =R20
.def bitcnt =R21
.def counter =R25
.cseg
.org 0
rjmp reset
;********************************************************************
;* "TIM0_OVF" - Timer/counter overflow interrupt handler
;*
;* The overflow interrupt increments the "timerL" and "timerH"
;* every 64us and 16,384us.
;*
;* Number of words: 7
;* Number of cycles: 6 + reti
;* Low registers used: 1
;* High registers used: 3
;* Pointers used: 0
;********************************************************************
.org OVF0addr
TIM0_OVF:
in S,sreg
inc timerL ;Updated every 64us
inc inttemp
brne TIM0_OVF_exit
inc timerH
TIM0_OVF_exit:
out sreg,S
reti
;=================================================================
; initiallizing Timer and PortB and enables interrupts.
;=================================================================
reset:
ldi temp,low(RAMEND) ;Initialize stackpointer
out SPL,temp
ldi temp,1 ;Timer/Counter 0 clocked at CK
out TCCR0,temp
ldi temp,1<<TOIE0 ;Enable Timer0 overflow interrupt
out TIMSK,temp
ldi temp,0b00000001 ;PB0 output
out DDRB,temp
ldi temp,0b00000100 ;pull-up resistor on PB2
out PORTB,temp
sei ;Enable global iterrupt
;=================================================================
; Main program
;=================================================================
main:
rcall delayTime
sbis PINB,SW ;is button pressed?
rcall switchRelay ;yes -> switch (invert) relay
rcall detect ;Call RC5 detect routine
cpi system,SYS_ADDR ;Respponds only at the specified address (philips TV)
brne release
andi command,0x3F ;Remove control bit
cpi command,on_key ; command = on_key (7) ?
brne release ;no -> jump to release
sbi PORTB,POWER ;yes -> switch device ON
rjmp main
release:
cpi command,off_key ; command = off_key (9) ?
brne release_sub ;no -> jump to release_sub
cbi PORTB,POWER ;yes -> switch device OFF
release_sub:
clr command
rjmp main
;********************************************************************
;* "detect" - RC5 decode routine
;*
;* This subroutine decodes the RC5 bit stream applied on PORTB
;* pin "INPUT".
;*
;* If successe: The command and system address are
;* returned in "command" and "system".
;* Bit 6 of "command" holds the toggle bit.
;*
;* If failed: $FF in both "system" and "command"
;*
;* Crystal frequency is 4MHz
;*
;* Number of words: 72
;* Low registers used: 3
;* High registers used: 6
;* Pointers used: 0
;********************************************************************
detect:
clr inttemp
clr timerH
detect1:
clr timerL
detect2:
cpi timerH,8 ;If line not idle within 131ms
brlo dl1
rjmp fault ; then exit
dl1:
cpi timerL,55 ;If line low for 3.5ms
brge start1 ; then wait for start bit
sbis PINB,INPUT ;If line is
rjmp detect1 ; low - jump to detect1
rjmp detect2 ; high - jump to detect2
start1:
cpi timerH,8 ;If no start bit detected
brge fault ;within 130ms then exit
sbic PINB,INPUT ;Wait for start bit
rjmp start1
clr timerL ;Measure length of start bit
start2:
cpi timerL,17 ;If startbit longer than 1.1ms,
brge fault ; exit
sbis PINB,INPUT
rjmp start2
;Positive edge of 1st start bit
mov temp,timerL ;timer is 1/2 bit time
clr timerL
mov ref1,temp
lsr ref1
mov ref2,ref1
add ref1,temp ;ref1 = 3/4 bit time
lsl temp
add ref2,temp ;ref2 = 5/4 bit time
start3:
cp timerL,ref1 ;If high periode St2 > 3/4 bit time
brge fault ; exit
sbic PINB,INPUT ;Wait for falling edge start bit 2
rjmp start3
clr timerL
ldi bitcnt,12 ;Receive 12 bits
clr command
clr system
sample:
cp timerL,ref1 ;Sample INPUT at 1/4 bit time
brlo sample
sbic PINB,INPUT
rjmp bit_is_a_1 ;Jump if line high
bit_is_a_0:
clc ;Store a '0'
rol command
rol system
;Synchronize timing
bit_is_a_0a:
cp timerL,ref2 ;If no edge within 3/4 bit time
brge fault ; exit
sbis PINB,INPUT ;Wait for rising edge
rjmp bit_is_a_0a ;in the middle of the bit
clr timerL
rjmp nextbit
bit_is_a_1:
sec ;Store a '1'
rol command
rol system
;Synchronize timing
bit_is_a_1a:
cp timerL,ref2 ;If no edge within 3/4 bit time
brge fault ; exit
sbic PINB,INPUT ;Wait for falling edge
rjmp bit_is_a_1a ;in the middle of the bit
clr timerL
nextbit:
dec bitcnt ;If bitcnt > 0
brne sample ; get next bit
;All bits sucessfully received!
mov temp,command ;Place system bits in "system"
rol temp
rol system
rol temp
rol system
bst system,5 ;Move toggle bit
bld command,6 ;to "command"
;Clear remaining bits
andi command,0b01111111
andi system,0x1F
ret
fault:
ser command ;Both "command" and "system"
ser system ;0xFF indicates failure
ret
;=================================================================
; delay routine
;=================================================================
delayTime:
ldi counter,255
delay:
dec counter
brne delay
ret
;=================================================================
; switch Relay (invert state) routine
;=================================================================
switchRelay:
sbis PINB,POWER ;pomin nastepna linie jesli 1
rjmp SetRelayON ;nie 1 -> SetRelayON
cbi PORTB,POWER ;wyczysc bit (przekaznik OFF)
ret
SetRelayON:
sbi PORTB,POWER ;ustaw bit (przekaznik ON)
ret
Problem polega na tym, ze uklad "nie zawsze dziala". Czasami wlacza / wylacza sie bez problemu innym razem musze kilkakrtonie nacisnac przycisk pilota, aby spowodowac zalaczenie / wylaczenie urzadzenia.
Czy ktos moglby mnie naprowadzic na wlasciwy kierunek?
Pozdrawiam