PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SIRCS Dekoder!



stowoda
16.10.2005, 10:46
Moin!

Würde gerne mit meine Sony Fernbedienung mienen PC steuern können..

Dazu sollte der PIC(16F84A) gemäß dem SIRCS Protokoll http://www.boehmel.de/sircs.htm, die KomandoBits detektieren und speichern,
sowie an den PC über rs232 senden.

Habe mir dazu einen Algorythmus einfallen lassen und ihn auch umgesetzt.
Vielleicht hat jemand Erfahrung in diesen Dingen und kann sich meinen Code kurz anschauen. Er ist gut kommentiert also keine Angst!

Werde versuchen die Senderoutine noch hinzuzufügen und falls alles gut geht (und der PC die richtigen bits empfängt) hier posten,
wenn nicht sowieso ;)

Bemerkung zu SIRCS:
Die ersten 7bits nach dem header(2.4ms) sind die KommandoBits, also liegt es nahe, nur die ersten Bits auszuhorchen und zu speichern,
anstatt den gesamten Code speichern zu müssen.


list p=16F84A

#include<P16F84A.INC>

__CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC
errorlevel -302

;************************************************* *****************
;* Variablen *
;************************************************* *****************
x_start Equ 0x20
x_data1 Equ 0x21
data1 Equ 0x22
x_bytes Equ 0x23
x_bit Equ 0x24
x_onetime Equ 0x25

;************************************************* *****************
;* Programmstart *
;************************************************* *****************
org 0x00
clrf PCLATH
clrf STATUS
clrf INTCON
goto INIT
org 0x04
goto INT_RT

;************************************************* *****************
;* Initialisierung *
;************************************************* *****************
INIT
bsf STATUS, RP0
movlw b'00000001'
movwf TRISB
movlw .0
movwf TRISA
movlw b'00000111'
movwf OPTION_REG
bcf STATUS, RP0
movlw b'10110000'
movwf INTCON
clrf PORTB
clrf x_start
clrf data1
clrf x_onetime
org 0x20
sl
sleep
goto $-1

;************************************************* ****************
;* Interrupt Routine *
;************************************************* ****************
INT_RT
btfss x_start, 0 ; got header already?
goto INT_naglowek ; NO
goto INT_bity ; YES --> get bits

;************************************************* ****************
;* detect header *
;************************************************* ****************
INT_naglowek ; get header
movlw .6 ; set counter for data1
movwf x_data1 ;
bsf STATUS, RP0
movlw b'10000010' ; Prescaler 1.795ms (2.4)
movwf OPTION_REG ; for header!
bcf STATUS, RP0
bcf INTCON, T0IF
movlw .34 ; loading TMR0 to count 1.8ms
movwf TMR0

btfss INTCON, T0IF ; TMR0 overflowed??
goto $-1 ; t < t < 3t
btfsc PORTB, 0 ; YES.. if RB0=0 got header
goto fehler ; header detection failed
bsf x_start, 0 ; marking that header already detected
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags
retfie ; sleep and wait for 1st bit

;************************************************* ******************
; detect bits *
;************************************************* ******************
INT_bity ; Initialization due to bit detection
bsf PORTB, 2 ; debug LED
btfsc x_onetime, 0
goto fehler
bsf STATUS, RP0
movlw b'00000001' ; Prescaler TMR0 0.8ms
movwf OPTION_REG
bcf STATUS, RP0
bcf INTCON, T0IF
movlw .35
movwf TMR0

btfss INTCON, T0IF ; TMR0 overflowed??
goto $-1 ; 1t < t < 2t
btfss PORTB, 0 ; if after 0.903ms RB=1
goto sv_one ; one was detected, store it !!
goto sv_zero ; zero was detected, store it !!

;************************************************* ******************
;* speichere 0 in data1 || store a zero in data1 *
;************************************************* ******************
sv_zero

btfsc x_data1, 7 ; data1 full ??
goto got_it ; YES -> continue with data2 !!
bcf STATUS, C ; NO --> move zero in C !!
rrf data1, F ; move C in data1.
decf x_data1, F ; in order to detect if data1 is full.
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags.
retfie ; sleep and wait for NEXT bit !!

;************************************************* *****************
;* speichere 1 in data1 || store a one in data1 *
;************************************************* *****************
sv_one

btfsc x_data1, 7 ; data1 full ??
goto got_it ; YES -> continue with data2 !!
bsf STATUS, C ; NO --> move one in C !!
rrf data1, F ; move C in data1.
decf x_data1, F ; in order to detect if data1 is full.
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags.
retfie ; sleep and wait for NEXT bit !!

got_it
bsf x_onetime, 0
;senderoutine PIC to rs232
;leider noch keine Idee.

fehler
bcf PORTB, 2 ; debug LED
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags.
retfie ; sleep and wait for header !!
end

Falls jemandem was zu bemerken hat bitte ich drum!
thx

Gruß
lk

PICture
16.10.2005, 19:18
Hi Stowoda!
Ich habe über C keine Ahnung. Aber all-gemain (kein Tippfehler):
Du willst Dein SIRCS Dekoder doch realisieren, dann mußt Du sowieso ensprechende Hardware irgendwann anschließen. Tun das jetzt, gleich am Anfang, dann hast Du "jemanden", der alle Deine Codes ohne Kommentar objectiv prüft. Wenn irgendwas nicht richtig funktioniert, dann bin ich sicher, dass Du den Fehler am schnellsten selber findest. Keine Angst vor der Hardware ich helfe Dir gerne.
MfG

stowoda
16.10.2005, 20:10
Hey PICture!

Habe die Hardware bereits realisiert. Ist zwar noch alles auf dem Steckbrett aber ich habe einen MAX232 mit den zugehörigen Kondensatoren sowie einen TSOP1740 mit dem F1684A verbunden.
Ich denke die Beschaltung ist ok, da ich diese bereits mit einem simplen Programm getestet habe, welches im 8n1 Format bei 9600bd, eine fest eingestellte Bitfolge sendet.
Mittlerweile habe ich auch eine Senderoutine hinzugefügt um im 7n1 Format, ebenfalls bei 9600bd, die KommandoBits der Fernbedienung zum PC zu senden.
Leider klappt das ganze nicht.

Wenn ich eine Taste auf der Fernbedienung drücke dann zeigt mein RS232_Terminal(Progg zum Empfang von Daten über die serielle Schnittstelle) folgendes:
1x Taste A: 127 (dezimal)
2x Taste A: 124
3x Taste A: 115
.
.
9x Taste A: 31


Wenn ich nun Die Verzögerungsschleife, die sich ganz am Ende des Programms befindet weglasse, so passiert folgendes:
1x Taste A: 127 124 115 79 63 126 121 103 31 127 124 115 79 (dezimal)
2x Taste A: 63 126 121 103 31 127 124 115 79 63 126 121 103 31 127 124 115 79 63 126 121
3x Taste A: 103 31 127 124 115 79 63 126 121 103 31 127 124 115 79 63 126 121 103 31 127
4x Taste A: 124 115 79 63 126 121 103 31 127 124 115 79 63 126 121 103 31 127 124 115 79

Es ist also die gleiche Bitfolge wie ohne Verzögerungsschleife am Ende, blos kommt mehr auf einmal an.

Übrigens ist es egal welche Taste auf der Fernbedienung ich betätige, es verhält sich so als wäre es ein und die selbe Taste(da der code sich nicht ändert)

hier der code

danke u Gruß
lk

list p=16F84A

#include<P16F84A.INC>

__CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC
errorlevel -302

;************************************************* *****************
;* Variablen *
;************************************************* *****************
x_start Equ 0x20
x_data1 Equ 0x21
data1 Equ 0x22
x_bytes Equ 0x23
x_bit Equ 0x24
x_onetime Equ 0x25
cycl_1 Equ 0x26
cycl_2 Equ 0x27
cnt Equ 0x28
cnt1 Equ 0x29

;************************************************* *****************
;* Programmstart *
;************************************************* *****************
org 0x00
clrf PCLATH
clrf STATUS
clrf INTCON
goto INIT
org 0x04
goto INT_RT

;************************************************* *****************
;* Initialisierung *
;************************************************* *****************
INIT
bsf STATUS, RP0
movlw b'00000001'
movwf TRISB
movlw .0
movwf TRISA
movlw b'00000111'
movwf OPTION_REG
bcf STATUS, RP0
movlw b'10110000'
movwf INTCON
clrf PORTB
clrf x_start
clrf data1
clrf x_onetime
org 0x20
sl
sleep
goto $-1

;************************************************* ****************
;* Interrupt Routine *
;************************************************* ****************
INT_RT
btfss x_start, 0 ; got header already?
goto INT_naglowek ; NO
goto INT_bity ; YES --> get bits

;************************************************* ****************
;* detect header *
;************************************************* ****************
INT_naglowek ; get header
movlw .6 ; set counter for data1
movwf x_data1 ;
bsf STATUS, RP0
movlw b'10000010' ; Prescaler 1.795ms (2.4)
movwf OPTION_REG ; for header!
bcf STATUS, RP0
bcf INTCON, T0IF
movlw .34 ; loading TMR0 to count 1.8ms
movwf TMR0

btfss INTCON, T0IF ; TMR0 overflowed??
goto $-1 ; t < t < 3t
btfsc PORTB, 0 ; YES.. if RB0=0 got header
goto fehler ; header detection failed
bsf x_start, 0 ; marking that header already detected
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags
retfie ; sleep and wait for 1st bit

;************************************************* ******************
; detect bits *
;************************************************* ******************
INT_bity ; Initialization due to bit detection
bsf PORTB, 2 ; debug LED
; btfsc x_onetime, 0
; goto fehler
bsf STATUS, RP0
movlw b'00000001' ; Prescaler TMR0 0.8ms
movwf OPTION_REG
bcf STATUS, RP0
bcf INTCON, T0IF
movlw .35
movwf TMR0

btfss INTCON, T0IF ; TMR0 overflowed??
goto $-1 ; 1t < t < 2t
btfss PORTB, 0 ; if after 0.903ms RB=1
goto sv_one ; one was detected, store it !!
goto sv_zero ; zero was detected, store it !!

;************************************************* ******************
;* speichere 0 in data1 || store a zero in data1 *
;************************************************* ******************
sv_zero

btfsc x_data1, 7 ; data1 full ??
goto got_it ; YES -> continue with data2 !!
bcf STATUS, C ; NO --> move zero in C !!
rrf data1, F ; move C in data1.
decf x_data1, F ; in order to detect if data1 is full.
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags.
retfie ; sleep and wait for NEXT bit !!

;************************************************* *****************
;* speichere 1 in data1 || store a one in data1 *
;************************************************* *****************
sv_one

btfsc x_data1, 7 ; data1 full ??
goto got_it ; YES -> continue with data2 !!
bsf STATUS, C ; NO --> move one in C !!
rrf data1, F ; move C in data1.
decf x_data1, F ; in order to detect if data1 is full.
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags.
retfie ; sleep and wait for NEXT bit !!

got_it
bsf x_onetime, 0
;************************************************* *****************
;* send 7 bits to rs232 || 9600bds 7n1 *
;************************************************* *****************
movlw .7 ; sending 7 bits
movwf cycl_1
bsf PORTB, 1
call Warte_s ; 1 Stopbit (1)
bcf PORTB, 1
call Warte_s ; 1 Startbit (0)

Send_1
rlf data1, f ; Bit into C flag !!
btfsc STATUS, C
bsf PORTB, 1 ; Hi if Bit = 1
btfss STATUS, C
bcf PORTB, 1 ; Lo if Bit = 0
call Warte_s ; wait 1 bit long !!
decfsz cycl_1, f ; already sent 7 bits ??
goto Send_1 ; NO
bsf PORTB, 1 ; YES -> send stopBit
call Warte_s ; wait 1 bit long !!
; call wrt ; loop (at the end)
goto fehler

Warte_s
movlw .16 ; 9600 Bps / 4 MHz
movwf cycl_2
Warte1
nop
nop
nop
decfsz cycl_2, 1
goto Warte1
return

fehler
bcf PORTB, 2 ; debug LED
bcf INTCON, T0IF ;
bcf INTCON, INTF ; Clearing interrupt flags.
retfie ; sleep and wait for header !!

;************************************************* *****************
;* loop *
;************************************************* *****************
;wrt
; movlw .255
; movwf cnt
; movwf cnt1
;wrt2
; decfsz cnt, F
; goto wrt3
; return
;
;wrt3
; decfsz cnt1, F
; goto wrt3
; goto wrt2
end

PICture
16.10.2005, 20:41
Es schaut so aus, das die Verzögerunsschleife nötig ist. Die Fernbedienungen arbeiten meistens nach dem Prinzip, das eine bestimmte Bitsfolge nach dem drücken einer Taste gesendet wird. Das alles ist auf menschliche "Geschwindigkeit" eingestellt. Das gleiche Problem habe ich gehabt bei einer Eigabe von Zahlen in einen Taschenrechner mit "künstlicher" Tastatur. Ich habe das problem damals so gelöst:
1. mit großer Verzögerung anfangen (z.B. 1s)
2. Verzögerung verkürzen bis Fehler auftreten
3. Das Doppelte der Verzögerung bei der Fehler aufgetreten sind als Nominalwert nehmen.
Vielleicht geht so bei Dir auch, probier mal!
MfG

stowoda
20.10.2005, 09:52
Hey, PICture!

Danke für Deine Vorschläge.
Habe das ausprobiert, aber leider hat es nicht gefunzt.
Darauf hin, da ich den Verdacht hegte die Senderoutine sei für die Fehler verantwortlich,
einen 16F88 genommen der einen USART besitzt.
Es klappt wuderbar! :)

Gruß
lk

PICture
20.10.2005, 11:29
Hallo stowoda!
Dann passt es, freue mich für Dich!
MfG