Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Interrupt da Timer0

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Interrupt da Timer0

Messaggioda Foto Utentedany192 » 18 nov 2011, 20:10

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)??
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

0
voti

[2] Re: Interrupt da Timer0

Messaggioda Foto Utentesimo85 » 18 nov 2011, 20:16

Ti riferisci ad un PIC o ad un microcontrollore Atmel?
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

0
voti

[3] Re: Interrupt da Timer0

Messaggioda Foto UtenteAjKDAP » 18 nov 2011, 20:24

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 :-)
Avatar utente
Foto UtenteAjKDAP
1.255 2 6 9
Expert EY
Expert EY
 
Messaggi: 796
Iscritto il: 17 mag 2006, 0:13
Località: nella coda dei pronti

0
voti

[4] Re: Interrupt da Timer0

Messaggioda Foto Utentesimo85 » 18 nov 2011, 20:26

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.
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

0
voti

[5] Re: Interrupt da Timer0

Messaggioda Foto Utentedany192 » 18 nov 2011, 20:42

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
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

0
voti

[6] Re: Interrupt da Timer0

Messaggioda Foto Utentesimo85 » 18 nov 2011, 20:46

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++; 
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

0
voti

[7] Re: Interrupt da Timer0

Messaggioda Foto Utentedany192 » 18 nov 2011, 22:51

Perfetto adesso faccio un po' di prove...penso che ne avrò per tutta la nottata :mrgreen: :mrgreen:
Grazie a tutti :ok:
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

0
voti

[8] Re: Interrupt da Timer0

Messaggioda Foto Utentedany192 » 19 nov 2011, 1:34

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
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

0
voti

[9] Re: Interrupt da Timer0

Messaggioda Foto Utentesimo85 » 19 nov 2011, 1:43

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?
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

0
voti

[10] Re: Interrupt da Timer0

Messaggioda Foto Utentedany192 » 19 nov 2011, 13:16

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.
Avatar utente
Foto Utentedany192
20 6
Frequentatore
Frequentatore
 
Messaggi: 123
Iscritto il: 1 ago 2011, 13:32
Località: everywhere

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti