< 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 |
---|---|
1 | 1.999 |
8 | 249 |
64 | 30,25 |
256 | 6,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:
- Imposta modo CTC (con confronto sul registro OCR1A) sul Timer1;
- Carica N nel registro OCR1A;
- Imposta la commutazione hardware del pin OC1A successivamente all'azzeramento del timer
- 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)