Grandegiove Inserito: 28 gennaio 2011 Segnala Share Inserito: 28 gennaio 2011 Buonasera... devo realizzare due conteggi di tempo con un PIC 18F4620:per fare ciò sto utilizzando con profitto il TIMER0 e il TIMER2: riesco ad effettuare il conteggio con buona precisione e ripetibilità; l'anomalia sta nella differenza del calcolo teorico rispetto al riscontro praticoTIMER 0 Obiettivo:un conteggio ogni secondo- f osc=20MHz -> 5 MIPS -> 1 conteggio ogni 0,2 us- prescaler 1:16 -> conteggio ogni 3,2 us- conteggio 8 bit (255) -> interrupt di fondo scala ogni 816 us- ogni 1225,5 interrupt dovrei contare 1 secondo (tralasciamo lo 0,5 e lo accettiamo come errore: 1225)Invece per ottenere il valore più viciono a 1 secondo (1,006 s) devo contare 1208 interrupt.. ?_?TIMER 2 Obiettivo:un conteggio ogni 18 ms- f osc=20MHz -> 5 MIPS -> 1 conteggio ogni 0,2 us- prescaler=1- postscale=1per ottenere un conteggio ogni 18 ms devo ottenere un fattore 90000 che ottengo imponendo il valore di compare PR2 del timer a 200 e contando 450 interrupt di fondo scala.Anche in questo caso per ottenere circa 18 ms devo mettere PR2=140, valore che differisce di molto dal valore calcolato.Dove sbaglio? Ecco il code.. sub procedure interrupt if(INTCON.TMR0IF)then 'è un INTERRUPT di TIMER 0 TMR0L=0 INTCON.TMR0IF=0 'set T0IE, clear T0IF Inc(cnt) 'increment value of cnt on every interrupt if(cnt>=1208)then '1,006 sec cnt=0 inc(sec) end if TMR0L=0 INTCON.TMR0IF=0 'set T0IE, clear T0IF end if if(PIR1.TMR2IF)then TMR2=0 PIR1.TMR2IF=0 Inc(cnt2) if(cnt2>=450)then 'è un INTERRUPT di TIMER 2 cnt2=0 '450+140PR2=28 Hz end if 'circa 1 km/h (27 Hz) TMR2 =0 PIR1.TMR2IF=0 end if end sub main: 'TIMER 2 ----------------------------------------------------------------------- T2CON=%00000100 'postscale=1 , acceso, prescaler 1 TMR2=0 PIE1.TMR2IE=1 PIR1.TMR2IF=0 PR2=140 'TIMER 0------------------------------------------------------------------------ T0CON=%11000011 'TIMER 0, 8 bit, gli assegno il PRESCALER, prescaler 16 TMR0L=0 'Valore iniziale TMR0H=0 '------------------------------------------------------------------------------- INTCON=%11100000 'Abilito interrupt timer0 e timer2 while(1) wend end. Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 29 gennaio 2011 Segnala Share Inserita: 29 gennaio 2011 Come misuri il secondo? Link al commento Condividi su altri siti More sharing options...
Grandegiove Inserita: 31 gennaio 2011 Autore Segnala Share Inserita: 31 gennaio 2011 Copiando u flag sull'uscita e connettendo un oscilloscopio digitale Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 31 gennaio 2011 Segnala Share Inserita: 31 gennaio 2011 Mmmh, sebra inspiegabile dato che il reale è anche più veloce del teorico. Hai verificato con l'oscilloscopio la reale frequenza del quarzo? Basta mettersi su uno dei 2 pins, quello corrispondente a osc_out. Link al commento Condividi su altri siti More sharing options...
RESNIC Inserita: 1 febbraio 2011 Segnala Share Inserita: 1 febbraio 2011 La soluzione a tale problema è :Dal momento in cui vado nell'interrupt, esegui i calcoli e poi azzero il Flag IF... questo tempo non viene conteggiato e quindi bastano meno count per arrivare al secondo... per risolvere il dilemma bisogna calcolare il tempo di esecuzione della routine di interrupt, e sottrarre questo tempo nel ragiungimento del target.Spero di esser stato chiaro .... Link al commento Condividi su altri siti More sharing options...
Grandegiove Inserita: 1 febbraio 2011 Autore Segnala Share Inserita: 1 febbraio 2011 Chiarissimo.. Mi stavo ponendo esattamente questo problema...CRedo proprio che tu abbia ragione..Inoltre anche se riazzero subito il flag nella routine si ha comunque un ritardo: credo quindi che lo stesso accesso alla subroutine abbia un ritardo.Grazie mille Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 1 febbraio 2011 Segnala Share Inserita: 1 febbraio 2011 (modificato) Non conosco il compilatore che stai usando; io uso CSC e non ho mai avuto di questi problemi. Inizialmente gestivo l'interrupt in asm proprio per evitare eventuali giri di pista a vuoto del compilatore, poi ho visto che non ci sono differenze. Devo aggiungere, ad onor del vero, che dal codice che hai usato probabilmente si può limare qualche cosuccia.Tanto per dare un'idea ecco le prime righe della funzione timer standard (per me). #int_timer1 void Timer10ms() /* Timer presettato a 10ms; conteggio = 10 tics ==> 100ms */ { set_timer1(0x3caf); // Caricato 15535 ==> // 50.000 * 4 * 50nsec = 10msec // 65535 - 50000 = 15535(0x3caf) ++tic_cnt; /* Il quarzo è da 20 MHz. Come si può vedere è solo necesario ricaricare il timer.Sono solo 4 istruzioni macchina (16 colpi di clock, overo 4 conteggi), che equivalgono ad un errore di 4 su 50000, cioè meno di 0.01%, errore minore della precisione del quarzo, almeno di un quarzo usato in un oscillatore di questo tipo. Modificato: 1 febbraio 2011 da Livio Orsini 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