Vai al contenuto
PLC Forum


Problemone Timer Pic


Grandegiove

Messaggi consigliati

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 pratico

TIMER 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=1

per 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


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

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

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

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: da Livio Orsini
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...