Pagina 1 di 2

Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 20:10
da dany192
Ciao a tutti ragazzi. Nei miei pochi progettini che ho realizzato finora con i microcontrollori non ho mai utilizzato i timer. Credo sia arrivato il momento di imparare però mi sono trovato di fronte ad un problemino...se devo generare un interrupt ogni 250 mS utilizzando un quarzo da 20 MHz, come dovrei fare?? Eseguendo i classici calcoli ottengo che per eseguire ogni istruzione il PIC impega 0,2 uS e quindi per ottenere l'overflow con conseguente interrupt ci vogliono 51,2 uS. Fin qui tutto corretto? :D

Se io ad esempio dovessi far accendere e spegnere un led ogni 250 mS come potrei gestire la situazione?? Ogni volta che si verifica l'interrupt dovrei mettermi ad incrementare un contatore fino ad arrivare a 4880 circa (che equivalgono a circa 250 mS)??

Re: Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 20:16
da simo85
Ti riferisci ad un PIC o ad un microcontrollore Atmel?

Re: Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 20:24
da AjKDAP
dany192 ha scritto:Fin qui tutto corretto? :D


Ehm, si, cioè andrebbe bene SE:
-SE stai utilizzando un determinato microcontrollore che incrementa il timer ogni 4 cicli di clock
-SE stai utilizzando un timer ad 8bit
-SE non utilizzi il prescaler e lo lasci a 1:1
-SE ad ogni routine di interrupt resetti il valore del timer a zero.

Sono tutti dettagli che non hai specificato, anche se penso che li hai semplicemente ignorati. Potrei pensare ad un PIC 16F ed all'utilizzo del Timer0 ad 8bit... ma meglio se ci dici tutto quanto :ok:

dany192 ha scritto:Se io ad esempio dovessi far accendere e spegnere un led ogni 250 mS come potrei gestire la situazione?? Ogni volta che si verifica l'interrupt dovrei mettermi ad incrementare un contatore fino ad arrivare a 4880 circa (che equivalgono a circa 250 mS)??


Se tutte le cose che ho scritto sopra sono vere, allora si, potresti fare una cosa del genere :-)

Re: Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 20:26
da simo85
Se ho capito bene ti riferisci ad un PIC visto che \frac{4}{20\text{MHz}} = 0.2\mu s
Tempo fa avevo scritto questo programma per una simulazione Supercar con un PIC16F886, che usa proprio il TMR0 e l'interrupt. Il flag del TMR0 è il T0IF.

Codice: Seleziona tutto
/*
   TMR0 INTERRUPT EXAMPLE by gohan
*/

#include <htc.h>

__CONFIG (0x014);

char i, bar, UP, count;

void main(void)
{   
   PORTC = 0x00;
   PORTB = 0x00;
   
   OPTION_REG = 0x87;
   INTCON = 0x80;
   ANSEL = 0x00;
   
   TRISB = 0x00;
   TRISC = 0x00;

   count = 0;
   i = 0;
   bar = 0x01;
   UP = 1;
   
   while(1)
   {      
      PORTC = bar;
      PORTB = count;   
      TMR0 = 0x16;
      T0IE = 1;
      while(!T0IF);
         ;
   }
}

void interrupt ISR(void)
{
   if(T0IF)
   {
      T0IF = 0;
   }
   
   if(UP)
   {
      if(i < 7)
      {
         bar <<= 1;
         i++;      
      }
      else
      {
         UP = 0;
         count++;
      }
   }

   if(!UP)
   {
      if(i > 0)
      {
         bar >>= 1;
         i--;
      }
      else
      {
         UP = 1;
      }      
   }
}

Il programma l'ho solo simulato, spero che ti sia utile.

Re: Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 20:42
da dany192
Scusate ragazzi, nella fretta ho dimenticato di specificare alcuni dettagli :mrgreen: Utilizzo un PIC, in particolare il 18F4550 con la gestione dell'USB che ho già implementato. Il prescaler, nel primo esempio che ho scritto non l'ho tenuto in considerazione (1:1) ma dovrei impostarlo facendo un paio di calcoli per vedere cosa mi conviene in termini di riduzione dell'errore per raggiungere i 250 mS. Ad esempio se imposto un 1:32, l'overflow dovrebbe esserci ogni 1,63 mS (con timer ad 8 bit). Ovviamente dopo l'overflow vado a resettare il registro.

in particolare comunque volevo capire se la tecnica che si deve utilizzare per riuscire ad ottenere un intervallo di tempo maggiore dell'overflow, è quella di contare un certo numero di interrupt con una variabile contatore. :D

Re: Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 20:46
da simo85
dany192 ha scritto:in particolare comunque volevo capire se la tecnica che si deve utilizzare per riuscire ad ottenere un intervallo di tempo maggiore dell'overflow, è quella di contare un certo numero di interrupt con una variabile contatore. :D

Si, per esempio nell'interrupt potresti fare così:
Codice: Seleziona tutto
   if(counter == N)
   {
      /* Do your job */
   }
   else
      counter++; 

Re: Interrupt da Timer0

MessaggioInviato: 18 nov 2011, 22:51
da dany192
Perfetto adesso faccio un po' di prove...penso che ne avrò per tutta la nottata :mrgreen: :mrgreen:
Grazie a tutti :ok:

Re: Interrupt da Timer0

MessaggioInviato: 19 nov 2011, 1:34
da dany192
Ragazzi sto avendo qualche problemino...la routine di gestione dell'interrupt è sempre la stessa?? Mi spiego meglio, sto lavorando con un HID con la libreria di MikroC ed ho già una routine che si occupa di eseguire la seguente istruzione:
Codice: Seleziona tutto
void interrupt(){
     HID_InterruptProc();
}


Adesso però devo gestire pure il timer0 ed ho lavorato in questo modo:
Codice: Seleziona tutto
void interrupt(){
     if(INTCON.TMR0IF){
         cnt++;                 //Incremento il contatore
         INTCON.TMR0IF = 0;     //Resetto l'overflow
     }
     else HID_InterruptProc();
}


Il firmware è molto lungo quindi non riesco nemmeno a postarlo però non mi funziona la parte del timer...nel main controllo la variabile "cnt" e quando arriva a 19 (sono passati circa 250ms) accendo un led però non va.
Ho dimenticato qualcosa nella configurazione dei registri??

Codice: Seleziona tutto
        // Configurazione registri interrupt
        INTCON = 0b11100000;
        INTCON2 = 0xF5;
        INTCON3 = 0xC0;
        RCON.IPEN = 0;                          // Disabilito livello di priorità
        PIE1 = 0;
        PIE2 = 0;
        PIR1 = 0;
        PIR2 = 0;
       
        // Configurazione Timer - Overflow
        T0CON = 0b11000111;                     //8bit - Prescaler 1:256

Re: Interrupt da Timer0

MessaggioInviato: 19 nov 2011, 1:43
da simo85
La prima cosa da fare, prima di qualsiasi cosa, in questo caso è resettare il flag di overflow e di interrupt del TMR0 sennò il micro non farà altro che attendere la richiesta di interruzione. Quindi io cambierei l'ordine delle istruzioni così:
Codice: Seleziona tutto
void interrupt()
{
     if(INTCON.TMR0IF)
     {
         INTCON.TMR0IF = 0;     //Resetto l'overflow
         cnt++;                 //Incremento il contatore
     }
     else HID_InterruptProc();
}


Non so cosa tu stia facendo in HID_InterruptProc(), ma non lo puoi fare all'interno della stessa funzione di interrupt dentro ad un if come fai con il TMR0?

Re: Interrupt da Timer0

MessaggioInviato: 19 nov 2011, 13:16
da dany192
La HID_InterruptProc() è una funzione standard della libreria di gestione dell'USB di MikroC e serve a mantenere la connessione.
Il documento ufficiale dice così: HID_InterruptProc() handles the USB communication and must be called as frequent as possible to maintain a secure connection.

Facendo un paio di prove ho scoperto che il problema stava nel fatto che non riuscivo a intercettare il valore preciso di cnt sul main, che dev'essere 19, ovvero 13107,2 uS x 19 = 249,04 mS . All'interno del main avevo questa situazione:
Codice: Seleziona tutto
//controllo timer
if(cnt==19){
      //sono trascorsi 249,04 mS
      PORTD.RD2 = ~PORTD.RD2; //lampeggio di un led per verifica
      cnt = 0;
};


Ho risolto mettendo un >= sul controllo di cnt.