Vai al contenuto
PLC Forum


Decoder Rc5


giagro

Messaggi consigliati

Salve.

Sto cercando di programmare un ricevitore IR, protocollo RC5 philips.

Ho comprato un ricevitore IR, TSOP a 36 KHz.

Il protocollo RC5 è costituito da un treno di 14 bit come illustrato in questo link: http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm

Ogni bit è della durata di 1,778 ms ed è costiutito da una prima metà "alta" (889 us) e una metà "bassa" (889 us): in questo caso trattasi di "0" logico. L'"1" logico è invece l'inverso.

Ho collegato i 3 piedini del TSOP alla massa , alla tensione (5V) e l'altro (OUT) ai piedini RB0 e RA4 del pic16f628.

Quindi ho scritto un codice che fa un polling sula porta RA4 dopo aver ricevuto il primo bit (START bit= 1 logico) con un external interrupt RB0 sul fronte di discesa (innanzitutto non ho capito bene perche' il primo bit lo prendo sul fronte di discesa e non di salita dato che io pensavo che in partenza l'RB0 e RA4 fossero a "0"...e invece col watch noto che partono a 1. Il ricevitore lavora per caso con logica inversa? Quindi riconosco uno "0" quando la prima metà è bassa????).

Dopo aver riconosciuto la prima variazione sull'ingresso che mi porta i 2 ingressi (RB0 e RA4) a "0" aspetto circa 400us (cosi mi porto a metà della seconda metà del primo bit) e mi aspetto che sia ancora basso. Così è.

Poi Aspetto 800 us (mi porto al centro del primo half bit del 2° bit) e vedo che è alto, quindi mi aspetto che dopo 800 us sia basso cosi da riconoscere che sia un altro 1 ed invece entro in un ciclo d'errore perche' mi risulta ancora per molto tempo "alto". Come mai secondo voi?

Il codice che ho scritto è questo:

_______________________________________

ERRORLEVEL 1

LIST P=16F648A

RADIX DEC

#include <P16F648A.INC>

; **************************************************************************

; ram segment

; all banks

SCAN_STATE EQU 0x70 ;Scan state pointer

IR_STATE EQU 0x71 ;IR receiver state machine

BIT_TIMER EQU 0x72 ;Bit timer

IR_ADDRESS EQU 0x73 ;IR shift register to store Start2,Toggle bit and Address (0AAAAATS)

IR_COMMAND EQU 0x74 ;IR shift register to store Command (00CCCCCC)

IR_FLAG EQU 0x75 ;Default: clrf IR_FLAG. Bit0=1 ---> IR_ADDRESS is complete ---> Store IR_COMMAND

; **************************************************************************

; ******************************* Constants ********************************

; **************************************************************************

TIMER_UPDATE equ 209 ;Timer update value (2 dead cycles): -50+3 ----> ? da ricontrollare il valore della costante da assegnare a TIMER_UPDATE

HALF_TIME equ 18 ;Number of timer counts per half bit : 900/50=18 ?

; **************************************************************************

; ******************************* MACROS ***********************************

; **************************************************************************

; bank change macros

bank0 MACRO

NOLIST

bcf STATUS,RP0

bcf STATUS,RP1

LIST

ENDM

;

bank1 MACRO

NOLIST

bsf STATUS,RP0

bcf STATUS,RP1

LIST

ENDM

;

bank2 MACRO

NOLIST

bcf STATUS,RP0

bsf STATUS,RP1

LIST

ENDM

;

bank3 MACRO

NOLIST

bsf STATUS,RP0

bsf STATUS,RP1

LIST

ENDM

;-----------------------------------------------------------------------------

;

; Reset vector

;

;-----------------------------------------------------------------------------

; ROM SEGMENT

ORG 0 ; reset address

goto init ; Get the system going

ORG 4 ; interrupt address

; goto intrr

;****************************************

; interrupt response routine

;****************************************

intrr:

; save status

NOP

NOP

retfie

;****************************************

; end interrupt routine

;****************************************

;-----------------------------------------------------------------------------

;

; Get started

;

;-----------------------------------------------------------------------------

init: movlw 0x70 ;Clear memory

movwf FSR

movlw 10 ;Clear a total of 10 RAM addresses (from 0x70 TO 0x7A)

movwf 0x79 ;use 0x79 address ram to countdown 10 times

clrmem: clrf INDF ;Clear this address

incf FSR ;Increment pointer

decfsz 0x79 ;Decrement counter from 10 to 0.

GOTO clrmem ;Repeat until done

bank1 ;Select bank 1 of register file

movlw 11011111B ;Timer mode without pre-scaler

movwf OPTION_REG

movlw 00010000B ;Only PA4 is an input

movwf TRISA

movlw 00000001B ;All Port B are outputs, just RB0/int is input

movwf TRISB

bank0 ;Select bank 0 of register file

movlw 00000000B ;Disable all interrupts

movwf INTCON

movlw IR_STATE_0 ;Init IR receiver state machine

movwf IR_STATE

clrf PCLATH ;All indirect jumps are on page 0!

movlw TIMER_UPDATE ;Get the timer started

movwf TMR0 ;TMR0 = -50+3 (x contare 50us)

;******************************************************************************

;------------------------------------------------------------------------------

;

; <<<<<<<<<<<<<<< Main program loop >>>>>>>>>>>>>>>>

;

;------------------------------------------------------------------------------

;*******************************************************************************

main:

;----------------------------------------- CALL THE IR RECEIVER STATE MACHINE--

CALL IR_MACHINE ;Call the IR receiver state machine

;------------------------------------------------------- SYNC MAIN WITH TIMER--

sync: btfsc TMR0,7 ;Wait until bit 7 of TMR = 0. Roll over ---> bit 7=0

GOTO sync ;Not 0 yet!

movlw TIMER_UPDATE ;Reload timer again because 50us are expired as due.

addwf TMR0,F

GOTO main

;-----------------------------------------------------------------------------

;

; IR receiver state machine

;

;-----------------------------------------------------------------------------

IR_MACHINE: movf IR_STATE,W ;Jump to present state

movwf PCL

;--------------------------------------- STATE 0, WAIT FOR BEGIN OF START BIT--

IR_STATE_0: btfsc PORTA,4 ;Input still high?

RETURN ;Yes! Nothing to do

movlw 8 ;Wait until we're in the center of the (HALF_TIME/2-1=8 circa)

movwf BIT_TIMER ; start pulse=8

movlw IR_STATE_1 ;Next stop is state 1

movwf IR_STATE

RETURN

;*******************************************************************************

;--------------------------- STATE 1, START BIT DETECTED, CHECK IF IT IS REAL--

IR_STATE_1: decfsz BIT_TIMER ;Wait until center of start pulse (ripete x 8 volte 50us cosi da ottenere 400 us circa il che significa che c troviamo a metà della second half dello start bit)

RETURN ;Time's not up yet!

btfsc PORTA,4 ;Is the input still low?

GOTO IR_ERROR_1 ;Nope! Exit with error

movlw HALF_TIME ;Set interval to the center of the

movwf BIT_TIMER ; first half of the next bit

movlw 00000010B ;Prepare the shift address register

movwf IR_ADDRESS

movlw 00000100B ;Prepare the shift command register

movwf IR_COMMAND

movlw IR_STATE_2 ;Prepare for next stop

movwf IR_STATE

RETURN

;*******************************************************************************

;----------------------------------- IR STATE 2, WAIT FOR FIRST HALF OF A BIT--

IR_STATE_2: decfsz BIT_TIMER ;Wait until center of first half of bit

RETURN ;Keep waiting!

movlw IR_STATE_3 ;Next state is 3 if input is high

btfss PORTA,4

movlw IR_STATE_4 ;Input is low, next state is 4

movwf IR_STATE

movlw HALF_TIME ;Restart bit timer

movwf BIT_TIMER

RETURN

;*******************************************************************************

;--------------- IR STATE 3, FIRST HALF WAS HIGH NOW IT MUST BE LOW FOR A "1"--

IR_STATE_3: decfsz BIT_TIMER ;Wait until center of 2nd half of bit

RETURN ;Keep waiting!

btfsc PORTA,4 ;Is input high now?

GOTO err ;Nope! It's an error!

bsf STATUS,C ;A 1 was received, shift it in result

btfss IR_FLAG,0 ;if Bit0_flag=0 ---> go to address to store it

GOTO ADDRESS_1

;-------- flag=1 -------

COMMAND_1: rlf IR_COMMAND,F

movlw HALF_TIME ;Restart bit timer

movwf BIT_TIMER

movlw IR_STATE_2 ;In case we need some more bits

btfsc STATUS,C ;We're done when Carry is 1

movlw IR_STATE_5 ;Carry is 1, received entire message

movwf IR_STATE

RETURN

;-------- flag=0 -------

ADDRESS_1: rlf IR_ADDRESS,F

movlw HALF_TIME ;Restart bit timer

movwf BIT_TIMER

movlw IR_STATE_2 ;In case we need some more bits

btfsc STATUS,C ;We're stored Address completely when Carry is 1

bsf IR_FLAG,0 ;set Bit0_flag=1 ---> Address stored in IR_ADDRESS. Now we'll store the command in IR_COMMAND

movwf IR_STATE

RETURN

err: movlw IR_ERROR_0 ;Wait until input gets high before

movwf IR_STATE ; returning to state 0

RETURN

;*******************************************************************************

;--------------- IR STATE 4, FIRST HALF WAS LOW NOW IT MUST BE HIGH FOR A "0"--

IR_STATE_4: decfsz BIT_TIMER ;Wait until center of 2nd half of bit

RETURN ;Keep waiting!

btfss PORTA,4 ;Is input high now?

GOTO IR_ERROR_1 ;Nope! It's an error!

bcf STATUS,C ;A 0 was received, shift it in result

btfss IR_FLAG,0 ;if Bit0_flag=0 ---> go to address to store it

GOTO ADDRESS_0

;-------- flag=1 -------

COMMAND_0: rlf IR_COMMAND,F

movlw HALF_TIME ;Restart bit timer

movwf BIT_TIMER

movlw IR_STATE_2 ;In case we need some more bits

btfsc STATUS,C ;We're done when Carry is 1

movlw IR_STATE_5 ;Carry is 1, received entire message

movwf IR_STATE

RETURN

;-------- flag=0 -------

ADDRESS_0: rlf IR_ADDRESS,F

movlw HALF_TIME ;Restart bit timer

movwf BIT_TIMER

movlw IR_STATE_2 ;In case we need some more bits

btfsc STATUS,C ;We're stored Address completely when Carry is 1

bsf IR_FLAG,0 ;set Bit0_flag=1 ---> Address stored in IR_ADDRESS. Now we'll store the command in IR_COMMAND

movwf IR_STATE

RETURN

;*******************************************************************************

;-------------------------- IR STATE 5, MESSAGE RECEIVED, START PROCESSING IT--

IR_STATE_5:

; ? use the 14 bits received in the better way ?

movlw IR_STATE_6 ;Done enough for now. Let's finish it

movwf IR_STATE ; in the last state

RETURN

;*******************************************************************************

;---------------------------------- IR STATE 6, WAIT FOR INPUT TO RETURN HIGH--

IR_STATE_6:

IR_ERROR_0: movlw IR_STATE_0 ;Reset state machine only if input is high

btfsc PORTA,4 ;

movwf IR_STATE ;if input is still low come back in IR_STATE_6 until input became high

RETURN

;*******************************************************************************

;-----------------------------------------------------------IR ERROR STATE 1--

IR_ERROR_1 movlw IR_STATE_0 ;Return to IR state 0

movwf IR_STATE

RETURN

;****************************** end IR receiver state machine ********************************************************

;*********************************************************************************************************************

nop

nop

END

--------------------------------------------------------------------------------------------------

;N.B.

;1) I RETURN dei singoli IR_STATE_X & IR_ERROR riportano alla CALL IR_MACHINE del main loop!!

;2) Ho inserito un registro (IR_FLAG). Setto il bit 0 d tale registro quando il carry del registro IR_ADDRESS va a '1' così da capire

; che ho ricevuto i primi 8 bit (0AAAAATS) e posso quindi passare a ricevere e memorizzare i 6bit del command in IR_COMMAND.

; Il primo start bit (che dovrà esser 1 affinche sia un treno d impulsi valido) non viene inserito in IR_ADDRESS che conterrà quindi

; solo 7 bit significativi.Il bit 7 varrà quindi 0 al termine della ricezione.

______________________________________________________-

Se qualcuno riesce a schiarirmi le idee e a risolvere qualche problema di base.

Innanzitutto i pull up vanno disabilitati? E l'oscillatore quale va impostato? Insomma non so configurare i configuration bit!

GRAZIE!

Link al commento
Condividi su altri siti


volevo precisare che in realtà quando ricevo la prima variazione su RA4 da ALTO a BASSO non entro in interrupt ma lo faccio con polling e rikiamo il main loop ogni 50 us circa.

Una domanda stupida: ma con il TSOP non ricevo mica i bit logici gia puliti?? Non credo vero??

Credo che ricevo i soliti alti seguiti da bassi e viceversa ed interpretare se trattasi di 0 o 1.

Grazie e scusate l'ignoranza

Link al commento
Condividi su altri siti

Non sono ancora entrato nel merito dell' RC5 anche se prima o poi vorrei farlo. Una domanda che mi viene in mente scorrendo rapidamente il programma: non e' che con quella modifica "manuale" del PCL si sconfina oltre il bordo di una pagina di 256 bytes? In generale sarebbe meglio salvare anche la parte alta dell'indirizzo e metterla nel PCLATH prima di modificare il PCL.

movlw IR_STATE_n

movwf IR_STATE

movlw HIGH(IR_STATE_n)

movwf H_IR_STATE

IR_MACHINE:

movf H_IR_STATE,W

movwf PCLATH

movf IR_STATE,W

movwf PCL

Link al commento
Condividi su altri siti

L'uscita del ricevitore TSOP è 5 volt a riposo. Si porta a zero solo durante il treno di impulsi a 36Khz.

Quindi la logica mi sembra inversa a quella che hai descritto.

Non è necessario fare il pull-up di RA4, anche se non dovrebbe dare fastidio.

Ciao

gariel

Link al commento
Condividi su altri siti

grazie sia a claudio che a gabriel.

Entrambe le risposte sono utili.

Claudio, come mai mi dici che non è necessario il pll up? e come potrei fare?

Per beccare i 14 bit hai un idea per farlo sapendo che ogni bit è costituiro da una metà ALTA e una BASSA di pari lughezza (889us)???

Praticamente ho questo problema:

Riconosco il primo bit "1".

Faccio passare 880 us circa e mi posiziono al centro della prima parte del 2°bit: noto che è ALTA e allora faccio passare altri 880 us (posizionandomi cosi a meta della seconda parte del 2° bit) e noto che risulta ancora ALTA e quindi vado in un ciclo di errore in quanto per esser un bit valido se la prima parte è alta mi aspetto che la seconda parte sia bassa.

Quale sarà il problema?

Qualcuno ha un codice per risolvere la codifica del RC5 in modo da avere come output un byte con l'ADDRESS del tasto premuto e un byte con il COMMAND??

GRAZIE MILLE. Siete molto competenti.

Link al commento
Condividi su altri siti

grazie mille gabriel.

Ho dato un occhiata al link ma sfortunatamente non conosco bene il francese e soprattutto a me servirebbe un codice esclusivamente per pic 1f628/a o 16f648/a perchè devo svolgere un progetto per la tesi con questo pic.

Vi sarei molto grato se potreste darmi una mano magari nel suggerirmi un altro link di codifica del protocollo rc5 per i pic menzionati o magri indicarmi a parole un metodo per decifrare i singoli bit.

Io avevo pensato di far nel seguente modo,ditemi se sbaglio qualcosa:

1) Se ho capito bene, grazie al TSOP ricevo un treno di 14 bit purtroppo non digitali ma ognuno dei quali è suddiviso da una metà (889us) ALTA ed una bassa (889us)

2) Ho scritto un main (che viene richiamato ogni 50 us circa) il quale salta ad un'etichetta la quale fa un polling sulla porta RA4 o RB0 (sono gli ingressi che ho collegato all'output del TSOP) e non appena noto che lo stato di questi pin passa da "1" a "0" riconosco che è arrivato il 1° bit (lo start bit che dovrebbe esser "1"). Mi trovo quindi all'inizio della seconda metà dello start bit, temporeggio 889/2 us (posizionandomi così al centro della seconda metà dello start bit) e verifico che gli ingressi siano ancora a "0". Cosi è.

3) Cerco ora di riconoscere il 2° bit,aspettando 889us circa (cercando di posizionarmi al centro della prima metà del bit). Noto che gli ingressi sono ora ad "1" (il che m fan intendere che sarà ancora un bit "1") e aspetto altri 889 us in modo da posizionarmi al centro della seconda metà del bit. Sfortunatamente però gli ingressi non sono a "0" come mi aspetto che siano, affinchè sia un bit valido, ma sono ancora ad"1" e quindi per come ho strutturato il firmware mi salta in una label di error perchè il bit non è valido. COME MAI?????

4) Quindi torno al punto 1 senza mai andar oltre il 2° bit.

5) sapete indicarmi cosa sbaglio??

6)Avete metodi migliori??

GRAZIE A TUTTI!

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...