MusicIsLife Inserita: 3 marzo 2010 Autore Segnala Share Inserita: 3 marzo 2010 (modificato) Provo a dare un'occhiata domani a lavoro.Il PIC che vorrei usare è il 16F84a, dato che è maggiormente disponibile qui in azienda.Se fosse possibile preferirei programmarlo in assembly piuttosto che in C.Comunque ho trovato un file di una decodifica Manchester R5 per i telecomandi della Philips. Domani lo carico sul forum.La decodifica che interessa a me, comunque, è quella che ha il bit "1" rappresentato da uno stato basso seguito da uno alto e il bit "0" viceversa. I primi due bit sono di start e sono rispettivamente un "1" ed uno "0". Modificato: 3 marzo 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 5 marzo 2010 Autore Segnala Share Inserita: 5 marzo 2010 (modificato) Metto qui la bozza della decodifica Manchester che sto implementando.L'ho debuggata con MPLAB e non mi da errori sintattici. Lunedì provo a caricarla nel PIC.Praticamente utilizzo 3 registri (KeyCode, KeyCode+1, KeyCode+2) per inserire i 18 bit dei dati in uscita dal sensore. I dati vengono letto dal pin RA0 di PORTA e poi, nello stato 5 della macchina a stati prendo i dati di questi registri e li mando in serie in uscita sul pin RB0 (e RB1 in versione invertita) in modo poi va visualizzare sull'oscilloscopio se la decodifica funziona.;----------------------------------------------------------------------------- PROCESSOR 16F84A RADIX DEC INCLUDE "P16F84A.INC" __CONFIG 3FF5H;per ora ho copiato questo valore di CONFIG, ma va controllato ;.................................................................; DICHIARAZIONI DEL FILE REGISTER;----------------------------------------------------------------------------- TestCode equ 12h IR_STATE equ 14h ;Registro associato alla IR state machineBIT_TIMER equ 15h ;Bit timerKeyCode equ 16h ;IR shift registermsDelayCounter equ 19hFLAG equ 1AhTEMP equ 1BhHCONT equ 1ChLCONT equ 1DhTEMP1 equ 1EhEADR equ 1FhContatore equ 20h;-----------------------------------------------------------------------------; COSTANTI;-----------------------------------------------------------------------------TIMER_UPDATE equ -50+3 ;Timer update value (2 dead cycles)HALF_TIME equ 850/50 ;Number of timer counts per half bit;Bisogna calcolare l'HALF_TIME in base al tempo di bit ;850 per il 38kHz;.................................................................IN equ 0OFF equ 1SUB equ 2VOLD equ 3VOLI equ 4IR_END equ 7TEST equ 6;-----------------------------------------------------------------------------;; Reset vector;;----------------------------------------------------------------------------- ORG 00h goto Start;:................................................................Start bsf STATUS,RP0 ;Entro nel banco 1 movlw b'00011111' ;Set PORTA come ingressi movwf TRISA movlw b'00000000' ;Set PORTB come uscite movwf TRISB ;movlw b'11011111' ;movwf OPTION_REG bcf STATUS,RP0 ;Torno al banco 0 movlw b'00000000' ;Tutti gli interrupts sono disabilitati movwf INTCON movlw IR_STATE_0 ;Inizializza la state machine per la decodifica Manchester movwf IR_STATE movwf TMR0 ;Inizializza TMR0 clrf KeyCode;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::MainLoop clrwdt LOOP CALL STATE_MACHINE ;Chiamata alla state machine per la decodifica Manchester CLRWDT GOTO LOOP;-----------------------------------------------------------------------------;; State machine for encoding MANCHESTER;;-----------------------------------------------------------------------------STATE_MACHINE movf IR_STATE,W ;W=IR_STATE movwf PCL ;Carica l'indirizzo di IR_STATE nel PC;---------------------------------------STATE 0, WAIT FOR BEGIN OF START BIT--IR_STATE_0 btfss PORTA,IN ;Se IN=0 esegue l'istruzione successiva (che fa uscire dalla subroutine) return ;Se IN=1 salta quest'istruzione e passa alla successiva perchè c'è il primo bit movlw HALF_TIME/2-1 ;Calcola metà del tempo di bit e carica il valore in W movwf BIT_TIMER ;BIT_TIMER=W movlw IR_STATE_1 ;Aggiorna lo stato della macchina a stati [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,1 ;Attende fino ad arrivare al centro del bit di start RETURN ;Time's not up yet! BTFSC PORTA,IN ;Is the input still low? [skip se il bit 4 di PORTA=0] GOTO IR_ERROR_1 ;Nope! Exit with error MOVLW HALF_TIME ;Set interval to the center of the [W=HALF_TIMER] MOVWF BIT_TIMER ;first half of the next bit [bIT_TIMER=HALF_TIMER] MOVLW b'01000000' ;Prepare the shift register MOVWF KeyCode ;Copia 01000000 in KeyCode CLRF KeyCode+1 ;Setta a 0 tutti i bit di KeyCode+1 CLRF KeyCode+2 ;Setta a 0 tutti i bit di KeyCode+2 MOVLW IR_STATE_2 ;Aggiorna lo stato della macchina a stati [Prepare for next stop] MOVWF IR_STATE RETURN;-----------------------------------IR STATE 2, WAIT FOR FIRST HALF OF A BIT--IR_STATE_2 DECFSZ BIT_TIMER,1 ;Wait until center of first half of bit RETURN ;Keep waiting! MOVLW IR_STATE_3 ;Salta a IR_STATE_3 se la prima metà del bit è alta BTFSS PORTA,IN MOVLW IR_STATE_4 ;Salta a IR_STATE_4 se la prima metà del bit è bassa MOVWF IR_STATE MOVLW HALF_TIME ;Azzera il 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,1 ;Wait until center of 2nd half of bit RETURN ;Keep waiting! BTFSC PORTA,IN ;Se la seconda metà del bit è =1, va alla label _ERROR GOTO _ERROR BSF STATUS,C ;A 1 was received, shift it in result RLF KeyCode,F ;Inserisce il Carry nella posizione 0 di KeyCode RLF KeyCode+1,F ;Shift di 1 bit a sinistra e ricopia in KeyCode+1 RLF KeyCode+2,F ;Shift di 1 bit a sinistra e ricopia in KeyCode+2 MOVLW HALF_TIME ;Azzera il 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_ERROR 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,1 ;Wait until center of 2nd half of bit RETURN ;Keep waiting! BTFSS PORTA,IN ;Is input high now? GOTO IR_ERROR_1 ;Nope! It's an error! BCF STATUS,C ;A 0 was received, shift it in result RLF KeyCode,F ;Shift di 1 bit a sinistra e ricopia in KeyCode RLF KeyCode+1,F ;Shift di 1 bit a sinistra e ricopia in KeyCode+1 RLF KeyCode+2,F ;Shift di 1 bit a sinistra e ricopia in KeyCode+2 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;--------------------------IR STATE 5, MESSAGE RECEIVED, START PROCESSING IT--IR_STATE_5 BCF STATUS,C ;Set CARRY=0 MOVLW b'00011000' ;W=24 MOVWF Contatore ;Contatore=W --> Contatore=24OUTPUT RLF KeyCode,F ;Shift di 1 bit a sinistra di tutti i 3 registri RLF KeyCode+1,F ;Considero il CARRY (dal KeyCode+2) per settare RLF KeyCode+2,F ;il bit in uscita BTFSC STATUS,C ;Se CARRY=0 salta l'istruzione successiva GOTO SET_1 GOTO SET_0SET_1 BSF PORTB,0 ;Set RB0=1 BCF PORTB,1 ;Set RB1=0 (Uscita invertita) GOTO CONTINUESET_0 BCF PORTB,0 ;Set RB0=0 BSF PORTB,1 ;Set RB1=1 (Uscita invertita) GOTO CONTINUECONTINUE ;BCF STATUS,C ;Set CARRY=0 DECFSZ Contatore,F ;Decrementa il contatore. Quando Contatore=0 skip istruzione successiva GOTO OUTPUT MOVLW IR_STATE_6 ;Aggiorna lo stato della macchina a stati MOVWF IR_STATE RETURN;----------------------------------IR STATE 6, WAIT FOR INPUT TO RETURN HIGH--IR_STATE_6IR_ERROR_0 MOVLW IR_STATE_0 ;Reset state machine only if input is BTFSC PORTA,IN ;high MOVWF IR_STATE RETURN;-----------------------------------------------------------IR ERROR STATE 1--IR_ERROR_1 MOVLW IR_STATE_0 ;Return to IR state 0 MOVWF IR_STATE RETURN;------------------------------------------------------------------------------END;--------------------------------FINE PROGRAMMA-------------------------Mi era venuto un dubbio: quando termina quel programma? perchè a me sembra che sia un loop continuo dato che nel MainLoop c'è una GOTO che continua a ciclare la macchina a stati per la decodifica. Mi sbaglio o non terminerebbe mai?Poi ho un'altra questione: ho un tempo di bit di 8uS. Come imposto l'HALF_TIME nelle costanti? Modificato: 5 marzo 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 5 marzo 2010 Segnala Share Inserita: 5 marzo 2010 Un micro non termina mai il programma, gira sempre, a meno che tu non lo metta in "sleep mode" ma poi ti serve qualcosa per risvegliarlo.In questo caso il loop controlla continuamente il pin di ingresso, se è 0 ripete il loop quando è 1 inizia la decodifica.HALF_TIME equ 850/50 ;Number of timer counts per half bit;Bisogna calcolare l'HALF_TIME in base al tempo di bit;850 per il 38kHzOvviamente dipende dal quarzo che stai usando Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 5 marzo 2010 Autore Segnala Share Inserita: 5 marzo 2010 (modificato) Grazie mille per le risposte Nikiki Allora le opzioni sono:A)Quarzo da 4MHzB)Quarzo da 10MHzNei due casi come si svolge il calcolo? Avevo poi la seguente questione:IR_STATE_0 btfss PORTA,IN ;Se IN=0 esegue l'istruzione successiva (che fa uscire dalla subroutine)return ;Se IN=1 salta quest'istruzione e passa alla successiva perchè c'è il primo bitmovlw HALF_TIME/2-1 ;Calcola metà del tempo di bit e carica il valore in Wmovwf BIT_TIMER ;BIT_TIMER=Wmovlw IR_STATE_1 ;Aggiorna lo stato della macchina a stati [Next stop is state 1]movwf IR_STATEreturnDa quello che ho capito la macchina a stati così come è implementata sta sempre nel primo stato ciclando fino a quando non rileva una transizione che porta un "1" sul pin di ingresso? Perchè non ho capito bene la transizione iniziale per attivare la macchina a stati. Quando la macchina va in STATE_1 e smette di aspettare una transizione sul pin di ingresso? Modificato: 5 marzo 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 6 marzo 2010 Segnala Share Inserita: 6 marzo 2010 Prima di tutto verifica il tipo di PIC che hai, se è un PIC16F84A-04/P lo puoi cloccare solo fino a 4 MHz.In questo firmware non è stato usato il timer0 (che sarebbe la cosa più logica) ma viene semplicemente caricato un valore in un registro e decrementato ad ogni ciclo fino ad arrivare a zero. Quindi la precisione del conteggio è influenzata dal numero di istruzioni eseguite.Facendo un conto approssimativo (potrei aver sbagliato... gli ho dato uno sguardo veloce) esegue 16 istruzioni iniziali per il caricamento dei registri e successivamente 10 istruzioni per ogni loop (sto parlando dello stato 1).Considerando che HALF_TIME viene dichiarato 850/50 (17) e che viene caricato diviso 2 -1 dal preprocessore, il valore iniziale di BIT_TIMER dovrebbe essere 7.Quindi abbiamo 16 istruzioni + 7 loop da 10 istruzioni l'uno per un totale di 86 istruzioni.Ogni istruzione viene eseguita in 4 cicli di clock, e a 32 KHz un ciclo dura 31,25 uS, quindi 31,25*4*86=10,750 mS. Possibile che in questo caso mezzo bit fosse 10,750 mS? Potrei aver fatto errori di calcolo, sbagliato a contare le istruzioni con i relativi tempi di esecuzione, ma il metodo è questo.Con 4 MHz un'istruzione dura esattamente 1 uS, solo le istruzioni di caricamento impiegano 16 uS, come fai a contare 4 uS del tuo mezzo bit?Anche cloccando a 20 MHz non ci riesci lo stesso, devi per forza usare il timer.Il metodo giusto è caricare il timer con il valore calcolato ed attendere l'interrupt dell'overflow. In questo modo non viene influenzato dalle istruzioni che ci sono in mezzo (il micro può fare tranquillamente altre cose) e l'incremento è dato solo dalla frequenza del quarzo/4 (più eventuali altre divisioni del prescaler).Ma per curiosità... perchè non usare il C? Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 6 marzo 2010 Autore Segnala Share Inserita: 6 marzo 2010 (modificato) Grazie per la risposta Allora, non uso il C per il semplice fatto che questo programmino l'avevo trovato all'incirca così poichè è stato utilizzato in azienda per dei sensori IR. Praticamente colui che mi ha mostrato il programma l'aveva preso da un sito internet che trattava la decodifica Manchester R5 per telecomandi Philips. Io ho quindi cercato di adattarlo alle mie esigenze togliendo le cose inutili e sistemando altre cose.Il fatto è che il programma originale è scritto in assembly e, quindi, non posso riprogrammarlo in C.Per il timer0 non saprei esattamente come implementarlo. Io mio problema è questo: arrivano 18 bit di dati + tempo di intervallo tra 1 stringa di bit e la successiva ogni 228uS dal sensore... fai conto che ogni bit è largo 8uS e, quindi, 18bitX8uS=144uS. Quindi la stringa di dati è di 144uS, mentre tra una stringa di bit (che iniziano con i 2 bit di start) e la successiva ci sono 228-144=84uS nei quali il segnale è portato a zero.Sta di fatto che ho 2 alternative:1)cerco di riprodurre FEDELMENTE in segnale ricevuto dal micro e decodificato mandandolo in uscita su un oscilloscopio. In questo caso dovrei, quindi, avere un segnale all'oscilloscopio simile a quello in ingresso del pic: 84uS di segnale a "0" tra una stringa di bit e l'altra e poi i miei 144uS di segnale decodificato, per un totale di 228uS.2)Fregarmene delle temporizzazioni e lasciare che anche se passano ad esempio 20uS tra 1 bit e l'altro non mi cambi la cosa.Ovviamente preferirei implementare la prima soluzione dato che avrei anche un confronto visivo tra ingresso del micro e uscita dal micro stesso.Si può fare quest'opzione? Come posso fare in modo che la lettura sulla porta e la scrittura nei registri non dipendano dalle istruzioni necessarie x fare queste operazioni? Modificato: 6 marzo 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 7 marzo 2010 Segnala Share Inserita: 7 marzo 2010 Usando il Timer0 del micro e l'interrupt.Quando devi contare un tempo preciso, carichi il timer con un valore opportunamente calcolato, questo viene incrementato dal clock/4, e quando "trabocca", nel program counter viene caricato il valore del vettore di interrupt e viene settato il flag del timer.Al vettore di interrupt ci metti un controllo per vedere cosa è successo (perchè il vettore di interrupt è unico per tutti gli eventi) e se trovi il flag del timer esegui quello che devi eseguire.Comunque con un micro da 4 MHz ci stai un po' preciso, quindi anche l'ingresso ti conviene metterlo sotto interrupt, perchè il ciclo di istruzioni che si occupa di leggerlo potrebbe perdere troppo tempo prima che si accorga dell'arrivo del bit.Oppure prendi un PIC che puoi cloccare a 20 MHz per avere un po' più di velocità di esecuzione.Devi lavorarci un po... Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 7 marzo 2010 Autore Segnala Share Inserita: 7 marzo 2010 (modificato) Sto cercando di capirci qualcosa anche se mi rendo conto che parto svantaggiato dato che non ho quasi mai programmato un PIC.Proviamo a ragionare: ho in ingresso una stringa di bit che variano ogni 8uS (tralasciando il tempo vuoto tra 1 stringa e la successiva). Se utilizzassi un quarzo da 4MHz ogni istruzione in assembler del programma verrebbe eseguita ogni 1uS. Ciò vorrebbe dire che il tempo massimo per decodificare un singolo bit in ingresso sarebbe di 8 istruzioni assembler. O__OMa non è possibile! Servono ben più di 8 istruzioni assembler per decodificare il bit in ingresso (anche tralasciando il fatto di copiarlo su un pin di uscita).[Piccola parentesi: ho letto sul datasheet che il PIC16F84A accetta fino a quarzi di 20MHz se non erro ]Poi una cosa che non ho capito è questa: mettiamo che io implemento il mio timer0 con un tempo adeguato affinchè vada in overflow nel tempo che mi interessa. Poi vado a leggere il bit nel registro che viene settato in caso di overflow e avvio una routine di interrupt (che dovrebbe fare cosa???). Il fatto è che questa routine di interrupt impiega del tempo per eseguirsi poichè anch'essa è composta da istruzioni che vengono eseguite in 1uS (o 2uS se impiegano 2 cicli macchina).Quindi come faccio? Sono un pochino confuso! Modificato: 7 marzo 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 8 marzo 2010 Segnala Share Inserita: 8 marzo 2010 devi solo testare il dato per vedere se è uno 0 o un 1 e copiarlo nel buffer di ricezione... 8 istruzioni potrebbero bastarti, magari evitando subroutine o salti inutili, ma come già detto saresti un po' nel preciso.L'ideale sarebbe appunto cloccare più veloce, ma non è vero che tutti i PIC16F84 puoi cloccarli fino a 20 MHz. Verso la fine del datasheet trovi come identificare il codice, il suffisso -04/P significa che può funzionare fino a 4 MHz, o almeno questo è il limite che ti garantisce Microchip, personalmente l'ho cloccato anche più veloce e funziona, ma non so se arriverà a 20. Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 11 marzo 2010 Autore Segnala Share Inserita: 11 marzo 2010 (modificato) Alla fine ho utilizzato un altro PIC, il 16F886 che ha anche i moduli per la EUSART, I²C o SPI; perlomeno la comunicazione con l'esterno (che sia PC con installato un programma per leggere i dati oppure un altro micro per fare altre elaborazioni) risulta essere più semplice.A titolo di test ho fatto in modo di girare i dati in ingresso (inseriti nei 3 registri KeyCode, KeyCode1, KeyCode2) in uscita, sul pin RA1 (e RA2 uscita invertita).Il programma che ho realizzato (e che simulandolo sembra funzionante nel modo corretto) si basa su una routine di interrupt che gestisce l'arrivo dei fronti dei singoli bit, sia che siano di salita, sia che siano di discesa (i bit sono in arrivo dal mio sensore sul pin RB0).Praticamente appena arriva un fronte si avvia la routine di interrupt e vado a leggere che valore ho in ingresso; se esso è alto allora il bit deve essere un "1" (poichè con la mia codifica Manchester una transizione basso->alto sarebbe un "1" logico). Se invece dopo l'interrupt del fronte ciò che leggo è basso, allora il bit deve essere uno "0".Il programma impiega circa 70uS per processare tutti i dati in uscita.Se avete voglia provate a dare un'occhiata al programma che posto qui. Suggerimenti e commenti sono ben accetti... Grazie ;----------------------------------------------------------------------------- PROCESSOR 16F886 RADIX DEC INCLUDE "P16F886.INC" __CONFIG _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_OFF & _WDT_OFF & _HS_OSC __CONFIG _CONFIG2, _WRT_OFF & _BOR40V ;-----------------------------------------------------------------------------; DICHIARAZIONI DEL FILE REGISTER;----------------------------------------------------------------------------- KeyCode equ 20h ;3 shift register per i dati in uscitaKeyCode1 equ 21h KeyCode2 equ 22hContatore equ 28h;-----------------------------------------------------------------------------; Reset vector;----------------------------------------------------------------------------- ORG 00h goto Start;-----------------------------------------------------------------------------; Routine di interrupt;----------------------------------------------------------------------------- ORG 04h CALL IR_STATE_0 nop nop nop nop nop movf PORTB,W BCF INTCON,RBIF RETFIE;-----------------------------------------------------------------------------Start banksel TRISA movlw b'00000000' ;Set PORTA come uscite movwf TRISA movlw b'11111111' ;Set PORTB come ingressi movwf TRISB movlw b'11111111' ;RBPU=1 & INTEDG=1 & TOCS=1 & T0SE=1 & PSA=1 & 1:128 prescaler movwf OPTION_REG movlw b'00000001' ;Abilita gli interrupt per i pin di PORTB movwf IOCB movlw b'10101000' ;Abilitati interrupt T0IE (Timer interrupt), RBIF (interrupt sugli ingressi del PORTB), RBIE movwf INTCON banksel ANSEL clrf ANSEL clrf ANSELH banksel TMR0 movlw b'11001110' movwf TMR0 ;Inizializza TMR0 a 206 clrf PORTA ;Azzera tutti i bit di PORTA clrf PORTB ;Azzera tutti i bit di PORTB MOVLW b'01000000' ;Prepare the shift register MOVWF KeyCode ;Copia 01000000 in KeyCode CLRF KeyCode1 ;Setta a 0 tutti i bit di KeyCode1 CLRF KeyCode2 ;Setta a 0 tutti i bit di KeyCode2 CLRWDT ;--------------------------LOOP PRINCIPALE-----------------------------------Int BTFSS INTCON,RBIF ;Verifica l'interrupt sul fronte di salita di RB1 nop goto Int ;altrimenti cicla nuovamente in modo periodico;-----------------------IR_STATE_0 [inizializzazione]-----------------------------------------IR_STATE_0 BTFSS PORTB,0 ;Legge l'ingresso su RB0. Se RB0=0 va in IR_STATE_1 GOTO IR_STATE_1 GOTO IR_STATE_2 ;Se RB0=1 va in IR_STATE_2;-----------------------IR_STATE_1 [setta il bit a "0"]---------------------------------------IR_STATE_1 BCF STATUS,C ;Set C=0 RLF KeyCode,F ;Shift di 1 bit a sinistra e ricopia in KeyCode RLF KeyCode1,F ;Shift di 1 bit a sinistra e ricopia in KeyCode1 RLF KeyCode2,F ;Shift di 1 bit a sinistra e ricopia in KeyCode2 BCF INTCON,RBIF ;Resetta il flag di interrupt su RB0 BTFSC STATUS,C ;Se C=1 ho finito di ricevere ed eseguo l'istruzione successiva GOTO IR_STATE_3 RETURN ;---------------------IR_STATE_2 [setta in bit ad "1"]-------------------------IR_STATE_2 BSF STATUS,C ;Set C=1 RLF KeyCode,F ;Shift di 1 bit a sinistra e ricopia in KeyCode RLF KeyCode1,F ;Shift di 1 bit a sinistra e ricopia in KeyCode1 RLF KeyCode2,F ;Shift di 1 bit a sinistra e ricopia in KeyCode2 BCF INTCON,RBIF ;Resetta il flag di interrupt su RB0 BTFSC STATUS,C ;Se C=1 ho finito di ricevere ed eseguo l'istruzione successiva GOTO IR_STATE_3 RETURN ;----------------------IR_STATE_3 [Processo il segnale presente nei 3 registri KeyCode]----IR_STATE_3 nop nop nop nop nop movf PORTB,W BCF INTCON,RBIF ;Resetta il flag di interrupt su RB0 MOVLW b'00011000' ;W=24 MOVWF Contatore ;Contatore=W --> Contatore=24 OUTPUT BCF STATUS,C ;Set CARRY=0 RLF KeyCode,F ;Shift di 1 bit a sinistra di tutti i 3 registri RLF KeyCode1,F ;Considero il CARRY (dal KeyCode+2) per settare RLF KeyCode2,F ;il bit in uscita BTFSC STATUS,C ;Se CARRY=0 salta l'istruzione successiva GOTO SET_1 GOTO SET_0SET_1 BSF PORTA,1 ;Set RA1=1 BCF PORTA,2 ;Set RA2=0 (Uscita invertita) GOTO CONTINUESET_0 BCF PORTA,1 ;Set RA1=0 BSF PORTA,2 ;Set RA2=1 (Uscita invertita) GOTO CONTINUECONTINUE DECFSZ Contatore,F ;Decrementa il contatore. Quando Contatore=0 skip istruzione successiva GOTO OUTPUT movlw b'10101000' ;Abilitati interrupt T0IE (Timer interrupt), RBIF (interrupt sugli ingressi del PORTB), RBIE movwf INTCON MOVLW b'01000000' ;Prepare the shift register MOVWF KeyCode ;Copia 01000000 in KeyCode clrf KeyCode1 ;Azzera KeyCode1 clrf KeyCode2 ;Azzera KeyCode2 GOTO Int ;Finito il ciclo riprende da capo ;-----------------------------------------------------------------------------END Modificato: 11 marzo 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 12 marzo 2010 Segnala Share Inserita: 12 marzo 2010 Secondo me ci sono degli errori.Questo è vero se il fronte di salita avviene in un preciso momento. Nel manchester ci sono dei fronti che non indicano l'1 logico... ad esempio se ci sono una sequenza di zeri, hai lo stesso dei fronti di salita, ma non c'è nessun 1 logico.Conoscendo la durata di un bit, devi misurare il tempo che passa dallo start, e vedere il fronte nel centro del bit.DEVI USARE IL TIMER!!! il tempo è fondamentale!Inoltre quando usi l'interrupt, come prima cosa ti devi preoccupare di salvare i registri che sporcherai durante la routine di interrupt, per poterli ripristinare prima del RETFIE. Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 12 marzo 2010 Autore Segnala Share Inserita: 12 marzo 2010 Il fatto è che io mi metto in ascolto solamente dei fronti di salita o discesa a metà bit. In questo modo, andando a leggere nell'immediato successivo del fronte centrale, se trovo un fronte basso è come se il bit fosse a "0", se invece fosse alto è come se fosse ad "1".Ho provato e la decodifica sembra funzionare.L'unico problema, forse, è se per caso il programma inizia a leggere quando la trasmissione è già in atto. Se per caso il pic inizia a leggere a metà treno di dati esce un casino assurdo poichè il contatore è tarato a 24 (3 registri da 8 bit l'uno)... e conta fino a 0, ovvero fino a quando TUTTI i bit sono stati mandati in uscita dai 3 registri sul pin RA1.Per quando riguarda i registri da salvare prima di entrare nella routine di interrupt hai perfettamente ragione. Però non mi sembrano critici dato che, praticamente, i registri KeyCodex vengono sempre sovrascritti. Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 21 marzo 2010 Segnala Share Inserita: 21 marzo 2010 Ma se non conti il tempo con precisione come fai a sapere se sei a metà bit?Anche se il tuo codice è relativamente semplice, è opportuno che tu tratti nel modo giusto gli interrupt, onde evitare imprevisti. E' una questione di principio. Anche nei pochi esempi nel datasheet mostra come fare. Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 22 marzo 2010 Autore Segnala Share Inserita: 22 marzo 2010 Semplicemente attendo fino al primo fronte di salita. Questo vuol dire che ho beccato il primo bit di start che è un 1. Per sapere se il bit che leggo è 1 o 0 leggo il valore dell'ingresso subito dopo il fronte che è appena arrivato; se esso è alto il valore è "1", se esso è basso il valore è "0".Comunque praticamente gestisco quell'interrupt con la sua routine utilizzando gli INTERRUPT-ON-CHANGE presenti sui pin del PORTB. Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 19 aprile 2010 Autore Segnala Share Inserita: 19 aprile 2010 (modificato) Allora, fino ad ora sembra funzionare tutto bene. Ho simulato il programma e funziona anche la teorica parte di programmazione del sensore.L'unico fatto è che ultimamente ho notato problemi all'uscita del PIC quando sono in modalità di lettura (ovvero la modalità di default, quando l'accelerometro trasmette segnali al pic e il pic effettua la decodifica Manchester).Mi spiego meglio: a volte fornisco alimentazione al circuito e il segnale in uscita del PIC è esattamente quello che mi aspetto. A volte, invece, alimento l'intero circuito e in uscita ho un bel "0" costante. Altre volte, invece, alimento l'intero circuito e per qualche secondo ho in uscita dal pic uno "0"; dopo un pò, invece, inizia a comparire il segnale che mi aspetterei.Pensavo fosse un problema di oscillazione del quarzo; per questo motivo, ora, ho spostato la parte del pic su millefori in modo da effettuare collegamenti più "stabili" e più corti. Utilizzo un quarzo da 20MHz e ho collegato i 2 condensatori da 18pF il più vicino possibile al quarzo e al pic.Mi sembra che il problema sia proprio il quarzo perchè con l'oscilloscopio a volte vedo delle sinusoidi sul pin CLKIN mentre sul CLKOUT un valore costante di tensione. A volte, invece, vedo su entrambi i pin delle sinusoidi. Qual è il segnale corretto che devo visualissare sui 2 pin sui quali è connesso il quarzo?Secondo voi qual è il problema?Il programma, comunque, l'ho debuggato interamente: è perfettamente funzionante a livello di simulatore al pc. La cosa strana è che prima funzionava tutto... poi, un pò alla volta, ho visto che alcune volte non funzionava... Ultimamente, invece, sono più le volte che non funziona. . xD Modificato: 19 aprile 2010 da MusicIsLife Link al commento Condividi su altri siti More sharing options...
Nikiki Inserita: 20 aprile 2010 Segnala Share Inserita: 20 aprile 2010 mi sembra strano che su un pin ci sia l'oscillazione e sull'altro no... come farebbe ad oscillare?... il quarzo non oscilla di sua iniziativa.Di solito si vede l'onda su entrambi i pin, ma su uno ha un'ampiezza minore.Se il Pic ha difficoltà ad oscillare potresti provare a fare un'oscillatore esterno...Il PIC lo alimenti a 5 Volt?Il pin di reset è collegato?Io continuo a pensare che questo è sbagliato, o ti sei spiegato male, oppure la decodifica così non può funzionare.l'1 logico non ce l'hai su "qualsiasi" fronte di salita... ma solo su quelli che accadono in un particolare momento! E quì ritiro in ballo il famoso timer, indispensabile per capire quel momento. Link al commento Condividi su altri siti More sharing options...
MusicIsLife Inserita: 24 aprile 2010 Autore Segnala Share Inserita: 24 aprile 2010 Ho sistemato i collegamenti e cambiato PIC. Non chiedetemi perchè ma il 16F886 non riuscivo a farlo oscillare a 20MHz neppure cambiando tutte e due le capacità.Ho usato un 16F628A e con quello oscilla senza problemi. Inoltre il pin dell MCLR è collegato con una resistenza a +5V e il PIC è alimentato a 5V.Nella configuration map ho ovviamente impostato HS come oscillatore esterno.Misteri dell'elettronica 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