giagro Inserito: 25 settembre 2005 Segnala Share Inserito: 25 settembre 2005 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.htmOgni 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 banksSCAN_STATE EQU 0x70 ;Scan state pointerIR_STATE EQU 0x71 ;IR receiver state machineBIT_TIMER EQU 0x72 ;Bit timerIR_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_UPDATEHALF_TIME equ 18 ;Number of timer counts per half bit : 900/50=18 ?; **************************************************************************; ******************************* MACROS ***********************************; **************************************************************************; bank change macrosbank0 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 timesclrmem: 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 RETURNerr: 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 More sharing options...
giagro Inserita: 25 settembre 2005 Autore Segnala Share Inserita: 25 settembre 2005 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 More sharing options...
Claudio F Inserita: 26 settembre 2005 Segnala Share Inserita: 26 settembre 2005 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_STATEIR_MACHINE: movf H_IR_STATE,W movwf PCLATH movf IR_STATE,W movwf PCL Link al commento Condividi su altri siti More sharing options...
Gariel Inserita: 26 settembre 2005 Segnala Share Inserita: 26 settembre 2005 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.Ciaogariel Link al commento Condividi su altri siti More sharing options...
giagro Inserita: 26 settembre 2005 Autore Segnala Share Inserita: 26 settembre 2005 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 More sharing options...
Gariel Inserita: 26 settembre 2005 Segnala Share Inserita: 26 settembre 2005 Il pull-up non è necessario perchè è già implementato nel ricevitore IR.Se vuoi la soluzione già pronta la trovi qui: http://angeliz.free.fr/Funziona perchè è stata da me testata tempo fa.Ciaogariel Link al commento Condividi su altri siti More sharing options...
giagro Inserita: 27 settembre 2005 Autore Segnala Share Inserita: 27 settembre 2005 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 More sharing options...
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora