PrettyPrint

sabato 14 agosto 2010

Timer AVR in 5min: 4) Generare forme d'onda con CTC

< Timer AVR in 5min: 3) VMLAB e linux Timer AVR in 5min: 5) Gen. forme d'onda PWM (fast) >




Ultima revisione: 26/Apr/2012 


quadra.zip


Supponiamo di avere il seguente compito:

Generare, con il timer1 da 16bit, un segnale rettangolare simmetrico (DC=50%) e unipolare avente frequenza di 1 kHz, usando come clock quello di sistema fc=4MHz

La commutazione del livello logico di un pin di uscita, ad intervalli di tempo regolari T, può essere vista come un'onda rettangolare simmetrica e unipolare (livelli di tensione 0V/VH):


Il periodo dell'onda quadra, che chiamiamo Ts, è evidentemente sempre pari a 2*T, ove T è il nostro tempo generato con il timer.

Nel compito assegnato, dunque abbiamo Ts=1/1000=1ms da cui ricaviamo T=0,5ms

A questo punto, possiamo prendere il software che abbiamo già scritto per il lampeggio del LED cambiando semplicemente il numero N calcolandolo per avere un tempo di 0,5ms invece di 1s

C'è però una soluzione migliore.

Con gli AVR (così come con altri micro) è possibile effettuare la commutazione del livello di uscita di un pin, non solo via software come si è fatto nella I parte (mediante un interrupt e un'operazione di ex-or) ma anche completamente via hardware, con tutti i vantaggi del caso.

Se, quindi, il nostro compito è semplicemente quello di commutare il livello di un piedino di uscita a intervalli di tempo regolari ovvero, in altre parole, generare un'onda quadra simmetrica è preferibile utilizzare sempre il modo CTC già visto, ma con un meccanismo hardware invece di uno software.

Nel modo CTC con meccanismo hardware non ci sono interrupt e relative routine di gestione da scrivere nel software; il modo CTC fa sempre il suo lavoro: allorquando il dato contenuto nel registro del timer1 TCNT1 eguaglia quello del registro OCR1A (1), al successivo impulso di clock avviene l'azzeramento del timer e il conteggio riparte.

Quello che cambia è cosa fare all'occorrenza dell'azzeramento: non si usa più un interrupt, ma avviene (totalmente via hardware) una commutazione del livello logico di un particolare piedino d'uscita chiamato OC1A; oppure, se configuriamo diversamente il nostro software, come vedremo, l'azzeramento ( ovvero V(t)=0V) o l'attivazione dell'uscita (ossia V(t)=VH, tipicamente 5V).

A differenza del "meccanismo software", che usa un interrupt, dove si è liberi di scegliere non solo cosa fare ogni T secondi, ma anche il piedino sul quale avere la commutazione, usando il modo CTC con il meccanismo hardware si è però vincolati a usare un preciso pin, riportato nel datasheet con il riferimento OC1A (che guardacaso negli ATmegax8 corrisponde proprio con PB1):



Il periodo Ts del segnale è



e quindi il tempo T del nostro timer, come già detto, dovrà essere pari a:



Determiniamo il numero N da caricare nel registro OCR1A per i diversi valori di prescaling: 1, 8, 64, 256 o 1024 tramite la nota formula:





ove il periodo Tc è immediatamente noto come reciproco della frequenza:



Calcoliamo per ogni valore di k, il relativo numero N:







k N
11.999
8249
64 30,25
2566,81
1024 0,95



A questo punto prendiamo in considerazione solo fattori di prescaler per i quali abbiamo numeri N rappresentabili dal timer a 16 bit (numeri interi e non superiori a 65535), quindi scartiamo da subito k=64, k=256 e k=1024.

Rimangono infine k=1 e k=8, dei due preferiamo il più piccolo (nessun prescaler) in corrispondenza del quale N=1999.

Scriviamo il pseudocodice:

  1. Imposta modo CTC (con confronto sul registro OCR1A) sul Timer1;
  2. Carica N nel registro OCR1A;
  3. Imposta la commutazione hardware del pin OC1A successivamente all'azzeramento del timer
  4. Imposta prescaler a 1 (nessun prescaler);


Vediamo le istruzioni, passo passo:

1. Imposta modo CTC (con confronto sul registro OCR1A) sul Timer1

E' la stessa configurazione già vista per il modo CTC con interrupt; bisogna attivare il solo bit WGM12 che si trova nel registro TCCR1B:

TCCR1B |= (1 << WGM12); // imposta il Timer1 in modo CTC (su OCR1A)



2. Carica N nel registro OCR1A;


L'istruzione di caricamento è immediata:
OCR1A = N;
ove N è la solita etichetta simbolica, che va definita all'inizio, con il consueto commento esplicativo sul tempo generato in corrispondenza del numero N:

#define N 1999 // T=0,5ms @4MHz :1



3. Imposta la commutazione hardware del pin OC1A successivamente all'azzeramento del timer


L'impostazione della commutazione hardware, avviene impostando i bit COM1A1 e COM1A0 del registro TCCR1A, che definiscono "cosa fare" sull'azzeramento del timer: 1) commutare l'uscita (toogling), 2) azzerare l'uscita, 3) settare l'uscita, come riportato nella tabella successiva:











che in codice avr-libc si traduce come:

TCCR1A |= (1 << COM1A0);  // Imposta toogle su OC1A




4. Imposta prescaler a 1 (nessun prescaler);

 
Dalla tabella 16-5 riportata nel datasheet dell'Atmega168, ricaviamo che bisogna attivare il solo bit CS10 del registro TCCR1B:




TCCR1B |= (1 << CS10) ; // nessun prescaling (k=1)




Combinando i vari frammenti di codice, siamo ora in grado di scrivere il software definitivo:



#include <avr/io.h>

#define N 1999  // T=0,5ms @4MHz :1

int main (void)

{


   DDRB |= (1 << PB1);  // Imposta il pin PB1(OC1A) come di uscita

   TCCR1B |= (1 << WGM12); // imposta il Timer1 in modo CTC (su OCR1A)

   OCR1A = N;  // carica N nel registro OCR1A

   TCCR1A |= (1 << COM1A0);  // Imposta funzione di commutazione su OC1A

   TCCR1B |= (1 << CS10) ; // nessun prescaling (k=1)



   // Da questo punto in poi il timer è avviato!



   while(1)

      {

        /* non fa niente...*/
        /* sul reset del timer (dopo il numero 1999) */
        /* avverrà la commutazione hardware del pin OC1A */

      }

Simuliamo il nostro software con vmlab (come già spiegato precedentemente) e il risultato è appunto un'onda quadra di 1kHz.




Per misurare la frequenza, cliccare sulla traccia e quindi sul pulsante Analyze.

Nello zip allegato, oltre al sorgente, c'è anche il file progetto (QUADRA.PRJ) per VMLAB.

----
Nota 1) E' possibile utilizzare, in alternativa al registro OCR1A, il registro ICR1 (v. datasheet per la diversa configurazione)

< Timer AVR in 5min: 3) VMLAB e linux Timer AVR in 5min: 5) Gen. forme d'onda PWM (fast) >





I contenuti di questo documento, sono stati resi possibili grazie ai seguenti strumenti gratuiti:
- LaTex online equation editor
- FidoCADJ (disegno grafici)
- Google Code Prettify (sorgenti con sintassi evidenziata)
- gEDA (disegno schemi elettrici)



Nessun commento:

Posta un commento