Go Down

Topic: Delay segnale variabile (Read 418 times) previous topic - next topic

ekjk

Dec 31, 2012, 10:55 am Last Edit: Dec 31, 2012, 02:07 pm by ekjk Reason: 1
Ciao a tutti,
vi rompo ancora  :)

Dunque, avevo realizzato un codice che varia il delay da applicare ad un segnale d'ingresso in base alla frequenza dello stesso ed ai valori salvati in memoria.

nel setup setto il timer1 in questo modo

Code: [Select]

// initialize Timer1
   cli();          // disable global interrupts
   TCCR1A = 0;     // set entire TCCR1A register to 0
   TCCR1B = 0;     // same for TCCR1B

   // set compare match register to desired timer count:
   // turn on CTC mode:
   TCCR1B |= (1 << WGM12);
   TCCR1B &= ~(1 << WGM10);
   TCCR1B &= ~(1 << WGM11);
   // Set for prescaler 8:
   TCCR1B |= (1 << CS11);
   TCCR1B  &= ~(1 << CS12);
   TCCR1B  &= ~(1 << CS10);
   // enable timer compare interrupt:
   TIMSK1 |= (1 << OCIE1A);
   // enable global interrupts:
   sei();


Poi quando arriva il fronte di salita del segnale scatta una routine che esegue questo codice per resettare il timer e farlo contare fino al delay voluto

Code: [Select]

OCR1A = dt;
     TCCR1B |= (1 << WGM12);
     TCCR1B &= ~(1 << WGM10);
     TCCR1B &= ~(1 << WGM11);
     TCCR1B |= (1 << CS11);
     TCCR1B &= ~(1 << CS12);
     TCCR1B &= ~(1 << CS10);


dopo di che quando il timer1 raggiunge il valore "dt" lancio la routine

Code: [Select]

ISR(TIMER1_COMPA_vect)
{
 TCCR1A = 0;     // set entire TCCR1A register to 0
 TCCR1B = 0;
 

 digitalWrite(PUOUT, 1);

}


Così alzo il pin di uscita che va a 1 dopo un certo ritardo.
Poi all'interno del loop dopo tot microsecondi (anche se so che la funzione micros non andrà bene perchè utilizzo il timer 1 per un altra cosa), tiro giù la stessa uscita con digitalWrite a 0. Non è importante che vada giù 100 piuttosto che 200 microsecondi dopo (poi al limite si può vedere di migliorare questa parte).

Quello che più mi preme è il fatto che dopo aver fatto
TCCR1A = 0;     // set entire TCCR1A register to 0
 TCCR1B = 0;

io setto il registro a 0 e quindi all'arrivo del fronte successivo devo re-inizializzarlo e questo mi porta via ben 30us...

Non esiste un modo per far si che quando ha finito di contare stia fermo a 0 o disabilitarlo in modo solo da farlo ripartire a contare da 0 al fronte successivo? Cioè senza inizializzarlo di nuovo.

Grazie mille

PaoloP

Chiedi a Leo72. E' lui l'esperto di Timer.  ;)

leo72

Intanto manipola direttamente le porte logiche senza usare la digitalWrite, così risparmi un bel pò di us.
Poi non ho capito la questione né cosa stai facendo... i timer sono di per sé contatori perenni per cui ogni volta che arrivano al valore max (che dipende dalla modalità scelta) si comportano in certe maniere, ossia possono invertire la direzione di incremento, possono ripartire da zero, ecc...) ma comunque non si fermano mai. Se vuoi bloccarli devi appunto farlo tu manualmente. Però ogni volta che fermi un timer e lo fai ripartire c'è un certo lag necessario al timer stesso per essere reinizializzato.

Go Up