Casa / Mezzi sociali / Implementazione dello shim utilizzando un interrupt. PWM software (PWM). Implementazione software del PWM

Implementazione dello shim utilizzando un interrupt. PWM software (PWM). Implementazione software del PWM

Nei dispositivi digitali, ad esempio, un microcontrollore può funzionare solo con due livelli di segnale, ad es. zero e uno o spento e acceso. Pertanto, puoi usarlo facilmente per monitorare lo stato del carico, come accendere o spegnere un LED. Puoi anche usarlo per controllare qualsiasi dispositivo elettrico utilizzando i driver appropriati (transistor, triac, relè, ecc.) Ma a volte è necessario qualcosa di più del semplice "accendere" e "spegnere" il dispositivo. Quindi, se vuoi controllare la luminosità di un LED (o una lampada) o la velocità di un motore DC, i segnali digitali semplicemente non possono farlo. Questa situazione è molto comune nella tecnologia digitale e si chiama Modulazione di larghezza di impulso (PWM).

Quasi tutti i microcontrollori moderni dispongono di hardware specializzato per la generazione di un segnale PWM. In questo tutorial impareremo le basi della tecnica PWM e successivamente vedremo come implementare il PWM utilizzando i microcontrollori AVR.

I dispositivi digitali come un microcontrollore possono generare solo due livelli sulle linee di uscita, alto = 5 V e basso = 0 V. Ma cosa succede se vogliamo ottenere 2,5 o 3,1 o ​​qualsiasi tensione compresa tra 0 e 5 V? Per fare ciò, invece di generare una tensione continua costante in uscita, genereremo un'onda quadra con livelli alto = 5 V e basso = 0 V (vedere Figura 1).

Fig. 1

La figura mostra che il segnale rimane alternativamente a livelli bassi e alti per qualche tempo. T0 - livello basso, T1 - livello alto. Il periodo del segnale sarà uguale a T = T0+T1. Periodo di impulso- questo è l'intervallo di tempo tra due punti caratteristici di due impulsi adiacenti. Tipicamente, il periodo viene misurato tra due aumenti o diminuzioni di impulsi adiacenti ed è indicato con la lettera maiuscola T.

Il periodo di ripetizione degli impulsi è direttamente correlato alla frequenza della sequenza degli impulsi e può essere calcolato utilizzando la formula: T = 1/F

Se la lunghezza dell'impulso T1 è esattamente uguale alla metà del periodo T, tale segnale viene spesso chiamato "onda quadra".

Il ciclo di lavoro degli impulsi è il rapporto tra il periodo di ripetizione degli impulsi e la loro durata ed è indicato con la lettera S: S = T/T1

Il duty factor è una quantità adimensionale e non ha unità di misura, ma può essere espresso in percentuale. Il termine si trova spesso nei testi inglesi Ciclo di lavoro, questo è il cosiddetto duty cycle o valore del duty cycle PWM. Il ciclo di lavoro D è il reciproco del ciclo di lavoro.

Fattore di riempimento solitamente espresso in percentuale e calcolato utilizzando la formula: D=1/S o così D = T1/T*100%

Nella figura sopra (Fig. 1) puoi vedere che T1 = T0, questo equivale alla metà del periodo di tempo. Quindi il ciclo di lavoro PWM è del 50%. Se la frequenza di tali impulsi è sufficientemente elevata (ad esempio, 5000 Hz), otteniamo metà di 5 V, ad es. 2,5 V. Pertanto, se l'uscita del controller è accoppiata al motore (utilizzando driver appropriati), funzionerà al 50% della sua velocità massima. La tecnica PWM sfrutta questo fatto per creare qualsiasi tensione tra due livelli (ad esempio tra 0 e 12 V). Il trucco è che quando il valore del ciclo di lavoro varia tra 0 e 100%, otteniamo la stessa percentuale di tensione in ingresso in uscita. Di seguito sono riportati alcuni esempi di segnali PWM con cicli di lavoro diversi.

Se si installa un filtro R/C in uscita, è possibile ottenere un livello di segnale CC puro anziché onde quadre. Ma questo non è necessario per i motori con spazzole o per il controllo della luminosità dei LED. Per fare ciò, è possibile applicare un segnale PWM direttamente al driver (ad esempio un transistor bipolare, MOSFET, ecc.).


In modalità operativa a 16 bit. Per timer si intende il relativo algoritmo di conteggio e il comportamento dell'uscita del formatore di impulsi ad esso associato, che è determinato da una combinazione di bit che specificano la modalità operativa del timer (WGMn3-0) e la modalità di generazione del segnale di uscita (COMnx1:0) . In questo caso, i bit per l'impostazione della modalità di generazione del segnale di uscita non influiscono sull'algoritmo di conteggio, perché L'algoritmo di conteggio dipende solo dallo stato dei bit per l'impostazione della modalità operativa del timer. Nelle modalità PWM, i bit COMnx1:0 consentono di abilitare/disabilitare l'inversione sull'uscita PWM generata (ovvero selezionare PWM con inversione o PWM senza inversione). Per le modalità non PWM, i bit COMnx1:0 determinano quale azione intraprendere quando si verifica una corrispondenza: resettare, impostare o invertire l'uscita (vedere anche "Blocco di condizionamento del segnale di uscita" e "Diagrammi temporali del timer-contatore a 16 bit") .

Operazione normale

La modalità operativa più semplice è la modalità normale (WGMn3-0 = 0b0000). In questa modalità, il contatore funziona come contatore sommatore (incrementale) e non viene ripristinato. Il contatore va in overflow quando passa attraverso il massimo di 16 bit. valore (0xFFFF) al limite di conteggio inferiore (0x0000). Durante il normale funzionamento, il flag di overflow del contatore del temporizzatore TOVn verrà impostato sullo stesso ciclo di clock quando TCNTn raggiunge lo zero.

In effetti, il flag di overflow TOVn è il 17° bit del contatore del timer, tranne per il fatto che viene solo impostato e non cancellato. Tuttavia, questa proprietà può essere utilizzata a livello di codice per aumentare la risoluzione del timer utilizzando un interrupt di overflow del timer, in seguito al quale il flag TOVn viene reimpostato automaticamente. Non esistono situazioni particolari per il normale funzionamento, quindi è possibile registrare un nuovo stato del contatore in qualsiasi momento.

In modalità normale, puoi utilizzare il blocco di acquisizione. È tuttavia necessario garantire che l'intervallo di tempo massimo tra il verificarsi di eventi esterni non superi il periodo di overflow del contatore. Se questa condizione non viene soddisfatta, è necessario utilizzare un interrupt di overflow del contatore del timer o un prescaler.

Il blocco di confronto può essere utilizzato per generare interrupt. Non è consigliabile utilizzare l'uscita OCnx per generare segnali durante il normale funzionamento, perché in questo caso, verrà spesa una parte significativa del tempo del processore.

Modalità di ripristino del timer della partita (CTC)

In modalità CTC (WGM01, WGM00 =0b10), il registro OCR0 viene utilizzato per impostare la risoluzione del contatore. Se è impostata la modalità CTC e il valore del contatore (TCNT0) corrisponde al valore del registro OCR0, il contatore viene azzerato (TCNT0=0). Pertanto, OCR0 specifica il conteggio massimo del contatore e, di conseguenza, la sua risoluzione. Questa modalità fornisce una gamma più ampia di regolazione della frequenza degli impulsi rettangolari generati. Semplifica inoltre il funzionamento del contatore di eventi esterni.

Nel reset del timer in modalità corrispondenza (WGMn3-0 = 0b0100 o 0b1100), la risoluzione del timer è impostata dai registri OCRnA o ICRn. In modalità CTC, il contatore (TCNTn) viene azzerato se il suo valore corrisponde al valore del registro OCRnA (WGMn3-0 = 0b0100) o ICRn (WGMn3-0 = 0b1100). Il valore del registro OCRnA o ICRn determina il limite di conteggio superiore e quindi la risoluzione del timer. Questa modalità fornisce una gamma più ampia di regolazione della frequenza degli impulsi rettangolari generati. Semplifica inoltre il funzionamento del contatore di eventi esterni. Il diagramma temporale del funzionamento del timer in modalità CTC è mostrato nella Figura 1. Il contatore (TCNTn) incrementa il suo stato finché non si verifica una corrispondenza con il valore di OCRnA o ICRn, quindi il contatore (TCNTn) viene reimpostato.

Figura 1 – Diagramma temporale per la modalità STS

Quando viene raggiunto il limite di conteggio superiore, è possibile generare un'interruzione utilizzando i flag OCFnA o ICFn corrispondenti ai registri utilizzati per impostare il limite di conteggio superiore. Se l'interruzione è abilitata, è possibile utilizzare la routine di interruzione per aggiornare il limite di conteggio superiore. Tuttavia, l'impostazione del valore superiore del conteggio vicino al valore del limite inferiore del conteggio quando il contatore funziona senza prescala o con un valore di prescala basso deve essere eseguita con estrema cautela, perché Non esiste un doppio buffering in modalità CTC. Se il valore scritto in OCRnA o ICRn è inferiore al valore corrente di TCNTn, il contatore si azzererà quando si verifica la condizione di corrispondenza quando raggiunge il valore massimo (0xFFFF), quindi si azzererà a 0x0000 e raggiunge il nuovo valore di OCRnA o ICRn. In molti casi, questa situazione non è auspicabile. Un'alternativa è la modalità PWM veloce, dove il registro OCRnA determina il limite di conteggio superiore (WGMn3-0 = 0b1111), perché in questo caso l'OCRnA è dotato di doppio buffer.

Per generare un segnale in modalità CTC, l'uscita OCnA può essere utilizzata per modificare il livello logico su ciascuna corrispondenza impostando la modalità di commutazione (COMnA1, COMnA0 = 0b01). Il valore OCnA sarà presente su un pin della porta solo se è specificata la direzione di uscita per quel pin. La frequenza massima del segnale generato è fOC0 = fclk_I/O/2 se OCRnA = 0x0000. Per altri valori OCRn, la frequenza del segnale generato può essere determinata dalla formula:

dove la variabile N specifica il fattore di divisione del prescaler (1, 8, 32, 64, 128, 256 o 1024).

Come nel funzionamento normale, il flag TOV0 viene impostato sullo stesso tick del timer quando il suo valore cambia da 0xFFFF a 0x0000.

Modalità PWM veloce

La modalità di modulazione della larghezza dell'impulso veloce (PWM) (WGMn3-0 = 0b0101, 0b0110, 0b0111, 0b1110, 0b1111) è progettata per generare impulsi PWM di frequenza maggiore. A differenza di altre modalità operative, questa utilizza il funzionamento del contatore unidirezionale. Il conteggio viene eseguito nella direzione dal limite di conteggio inferiore a quello superiore.

Se è impostata una modalità di uscita non invertente, quando TCNTn e OCRnx coincidono, il segnale OCnx viene impostato e ripristinato al limite di conteggio superiore. Se viene specificata la modalità di inversione, l'uscita OCnx viene reimpostata in caso di corrispondenza e impostata sul limite di conteggio alto. Grazie al conteggio unidirezionale, la frequenza operativa per questa modalità è doppia rispetto alla modalità PWM con correzione di fase, dove viene utilizzato il conteggio bidirezionale. La capacità di generare segnali PWM ad alta frequenza rende l'uso di questa modalità utile in attività di stabilizzazione della potenza, raddrizzamento e conversione da digitale ad analogico. L'alta frequenza, allo stesso tempo, consente l'utilizzo di elementi esterni di dimensioni fisicamente ridotte (induttori, condensatori), riducendo così il costo complessivo del sistema.

La risoluzione PWM può essere fissa a 8, 9 o 10 bit o impostata dal registro ICRn o OCRnA, ma non inferiore a 2 bit (ICRn o OCRnA = 0x0003) e non superiore a 16 bit (ICRn o OCRnA = 0xFFFF). La risoluzione PWM ad un dato valore limite superiore (UL) viene calcolata come segue:

Nella modalità PWM veloce, il contatore viene incrementato finché il suo valore non corrisponde a uno dei valori fissi 0x00FF, 0x01FF o 0x03FF (se WGMn3:0 = 0b0101, 0b0110 o 0b0111, rispettivamente), il valore in ICRn (se WGMn3:0 = 0b1110) o il valore in OCRnA (se WGMn3:0 = 0b1111) e quindi reimpostato al successivo tick dell'orologio del timer. Il diagramma temporale per la modalità PWM veloce è mostrato nella Figura 2. La figura mostra la modalità PWM veloce quando il registro OCRnA o ICRn viene utilizzato per impostare il limite superiore. Il valore TCNTn nel diagramma temporale viene mostrato come grafico della funzione per illustrare il conteggio unidirezionale. Il diagramma mostra le uscite PWM sia invertite che non invertite. Una breve linea orizzontale mostra i punti del grafico TCNTn in cui i valori OCRnx e TCNTnx coincidono. Il flag di interruzione OCnx viene impostato quando si verifica una corrispondenza.

Figura 2 – Diagramma temporale per la modalità PWM veloce

Il flag TOVn (Timer-Counter Overflow) viene impostato ogni volta che il contatore raggiunge il limite superiore. Inoltre, lo stesso impulso di clock, insieme al flag TOVn, può impostare i flag OCnA o ICFn se il registro OCRnA o ICRn viene utilizzato rispettivamente per impostare il limite superiore. Se uno di questi interrupt è abilitato, la routine di interrupt può aggiornare il limite di conteggio superiore e le soglie di confronto.

Se il valore del limite di conteggio superiore cambia, deve essere soddisfatta la condizione che il nuovo valore del limite superiore scritto sia maggiore o uguale ai valori in tutti i registri delle soglie di confronto. In caso contrario, non si verificherà mai una corrispondenza tra TCNTn e OCRnx. Si noti che quando si utilizzano valori limite superiori fissi, i bit non utilizzati vengono mascherati su 0 durante la scrittura nei registri OCRnx.

Il meccanismo di modifica del registro ICRn differisce da OCRnA quando viene utilizzato per impostare il limite superiore. Il registro ICRn non ha il doppio buffer. Ciò significa che se un valore piccolo viene scritto su ICRn mentre il contatore è in esecuzione con un prescaling minimo o nullo, esiste il rischio di scrivere un valore nel registro ICRn inferiore al valore corrente di TCNTn. Di conseguenza, in questa situazione verrà persa la partita in cima al conteggio. In questo caso, il contatore raggiungerà il suo valore massimo (0xFFFF), ripartirà da 0x0000 e solo allora genererà una corrispondenza. Il registro OCRnA contiene uno schema di doppio buffering, quindi può essere modificato in qualsiasi momento.

class="eliadunità">

Se viene effettuata una scrittura sull'indirizzo OCRnA, il valore viene effettivamente inserito nel registro buffer OCRnA. Se si verifica una corrispondenza tra TCNTn e l'inizio del conteggio, il ciclo di clock successivo del timer consiste nella copia del registro buffer nel registro della soglia di confronto OCRnA. Il registro viene aggiornato nello stesso ciclo di clock in cui TCNTn viene resettato e viene impostato il flag TOVn.

Si consiglia di utilizzare il registro ICRn per impostare il limite superiore se il limite di conteggio superiore è una costante. In questo caso anche il registro OCRnA viene liberato per generare un segnale PWM sull'uscita OCnA. Tuttavia, se la frequenza PWM cambia dinamicamente (a causa della modifica del limite superiore), in questo caso è più vantaggioso utilizzare il registro OCRnA per impostare il limite superiore, perché supporta il doppio buffering.

Nella modalità PWM veloce, le unità di confronto consentono di generare segnali PWM sui pin OCnx. Se COMnx1:0 = 0b10, allora viene impostata PWM senza inversione di uscita, e se COMnx1:0 = 0b11, allora viene impostata la modalità PWM con inversione di uscita (vedere Tabella 59). Il valore OCnx effettivo può essere osservato sul pin della porta se è impostato sulla direzione di uscita (DDR_OCnx). Il segnale PWM viene generato impostando (reimpostando) il registro OCnx quando si verifica una corrispondenza tra OCRnx e TCNTn e reimpostando (impostando) il registro OCnx insieme al ripristino del contatore (passaggio dal limite superiore al limite inferiore).

La frequenza PWM del segnale di uscita per un dato valore limite superiore (UL) è determinata dall'espressione:

dove N è una variabile che specifica il valore del coefficiente di predizione (1, 8, 32, 64, 128, 256 o 1024).

La scrittura dei valori limite nel registro OCRnx è associata a casi speciali nella generazione di impulsi PWM. Se OCRnx è impostato uguale al limite inferiore (0x0000), verrà visualizzato un breve impulso sull'uscita ogni (VP+1)esimo ciclo di clock del timer. Scrivere un valore uguale al limite superiore in OCRnx comporterà l'impostazione di un livello di registro costante. 1 o 0 in uscita (a seconda della polarità del segnale di uscita selezionato utilizzando il bit COMnx1:0).

Se è richiesta la generazione di onde quadre ad alta frequenza (impulsi rettangolari con un duty cycle del 2 o del 50% di riempimento), allora è necessario utilizzare la modalità PWM veloce con i bit COMnA1:0 = 0b01 impostati, che fa sì che il livello logico a l'uscita OCnA per commutare (invertire) ad ogni corrispondenza. Ciò è applicabile solo se viene utilizzato OCRnA per impostare il limite superiore (WGMn3-0 =0b1111). La frequenza massima dell'onda quadra generata in questo caso è fOCnA = fclk_I/O/2, se OCRnA = 0x0000. Questa funzionalità è simile alla commutazione OCnA in modalità CTC, ad eccezione del doppio buffering, presente in modalità PWM veloce.

Modalità di modulazione dell'ampiezza dell'impulso con correzione di fase (Phase Correct)

La modalità modulazione di larghezza di impulso con correzione di fase (PWM FC) (WGMn3-0 = 0b0001, 0b010, 0b0011, 0b1010 o 0b1011) è progettata per generare un segnale PWM con correzione di fase ad alta risoluzione. La modalità PWM FC si basa sul funzionamento bidirezionale di un timer-contatore. Il contatore passa dal limite basso (0x0000) al limite alto e poi torna dal limite alto al limite basso. Se la modalità di uscita del formatore di impulsi è impostata su non invertente, l'uscita OCnx viene ripristinata/impostata quando i valori TCNTn e OCRnx corrispondono durante il conteggio avanti/indietro. Se è impostata la modalità di uscita invertente, al contrario, durante il conteggio diretto, l'impostazione avviene e durante il conteggio inverso, l'uscita OCnx viene ripristinata. Con il funzionamento bidirezionale, la frequenza massima del segnale PWM è inferiore rispetto al funzionamento unidirezionale, tuttavia, a causa di caratteristiche come la simmetria nelle modalità PWM con funzionamento bidirezionale, è preferibile utilizzare queste modalità quando si risolvono i problemi di controllo dell'azionamento.

La risoluzione PWM in questa modalità può essere fissa (8, 9 o 10 bit) o ​​impostata utilizzando il registro ICRn o OCRnA. La risoluzione minima è 2 bit (ICRn o OCRnA = 0x0003) e la massima è 16 bit (ICRn o OCRnA = 0xFFFF). Se viene specificato un limite superiore, la risoluzione PWM in questa modalità viene determinata come segue:

Nella modalità PWM FC, il contatore viene incrementato fino a raggiungere uno dei valori fissi 0x00FF, 0x01FF o 0x03FF (rispettivamente per WGMn3-0 = 0b0001, 0b0010 o 0b0011), nonché un valore pari a ICRn (se WGMn3- 0 = 0b1010) o OCRnA (se WGMn3 :0 = 0b1011). Inoltre, quando viene raggiunto il limite superiore, il contatore cambia la direzione del conteggio. Il valore TCNTn rimane al limite superiore per un ciclo di clock del timer. Il diagramma temporale per la modalità PC PWM è mostrato nella Figura 3. La figura mostra la modalità PC PWM che utilizza il registro OCRnA o ICRn per impostare il limite superiore. Lo stato TCNTn è rappresentato come un grafico di funzione per illustrare il conteggio bidirezionale. La figura mostra l'uscita PWM sia non invertita che invertita. Le brevi linee orizzontali indicano i punti sul grafico TCNTn in cui si verifica una corrispondenza con il valore OCRnx. Il flag di interruzione OCnx viene impostato quando si verifica una corrispondenza.

Figura 3 – Diagramma temporale per la modalità PWM FC

Il flag TOVn (Timer-Counter Overflow) viene impostato ogni volta che il contatore raggiunge il limite inferiore. Se il registro OCRnA o ICRn viene utilizzato per impostare il limite superiore, il flag OCnA o ICFn viene impostato di conseguenza con lo stesso impulso di clock con cui il registro OCRnx è stato aggiornato dal registro buffer (all'inizio del conteggio). I flag di interruzione possono essere utilizzati per generare un'interruzione quando un contatore raggiunge un limite basso o alto.

Quando si modifica il valore del limite di conteggio superiore, è necessario assicurarsi che sia maggiore o uguale ai valori in tutti i registri di confronto. In caso contrario, non si verificherà mai una corrispondenza tra TCNTn e OCRnx. Si noti che quando si utilizzano valori di conteggio superiori fissi, i bit inutilizzati vengono azzerati durante la scrittura nei registri OCRnx. Il terzo periodo nella Figura 53 illustra il caso in cui una variazione dinamica del limite di conteggio superiore porta alla generazione di un impulso asimmetrico. Questa funzionalità si basa sul tempo di aggiornamento del registro OCRnx. Poiché l'aggiornamento OCRnx avviene all'inizio del conteggio, il periodo PWM inizia e termina all'inizio del conteggio. Ciò implica che la durata del conto alla rovescia è determinata dal valore limite superiore precedente e la durata del conteggio in avanti è determinata dal nuovo valore limite superiore. Se questi due valori sono diversi, anche la durata del conteggio in avanti e all'indietro sarà diversa. La differenza di durata porta all'asimmetria degli impulsi di uscita.

Se l'attività è modificare il limite superiore mentre il contatore è in funzione, invece di questa modalità si consiglia di utilizzare la modalità PWM PFC (correzione di fase e frequenza). Se viene utilizzato un valore limite superiore statico, non ci sono praticamente differenze tra queste modalità.

Nella modalità PWM FC, le unità di confronto consentono di generare segnali PWM sui pin OCnx. Se si imposta COMnx1:0 = 0b10, l'uscita PWM sarà senza inversione e se COMnx1:0=0b11, quindi con inversione. Il valore effettivo di OCnx può essere osservato sul pin della porta se il registro della direzione dei dati per quel pin della porta è impostato sulla direzione di uscita (DDR_OCnx). Il segnale PWM viene generato impostando (reimpostando) il registro OCnx quando i valori di OCRnx e TCNTn corrispondono durante il conteggio up e reimpostando (impostando) il registro OCnx quando c'è una corrispondenza tra OCRnx e TCNTn durante il conteggio indietro. La frequenza risultante del segnale PWM in modalità PWM FC a un determinato limite superiore (UL) può essere calcolata utilizzando la seguente espressione:

La scrittura dei valori limite nel registro OCRnx è associata a casi speciali nella generazione di segnali PWM nella modalità PWM FC. Se si imposta la modalità PWM senza inversione e si imposta OCRnx uguale al limite inferiore, l'uscita verrà impostata continuamente su log. 0 e se uguale al limite superiore, in uscita è sempre presente un log. 1. Per PWM con inversione i livelli indicati devono essere sostituiti con quelli opposti.

Se si specifica di utilizzare OCnA come limite superiore (WGMn3:0 = 0b1011) e si imposta COMnA1:0 = 0b01, verrà generata un'onda quadra all'uscita OCnA.

Modalità di modulazione dell'ampiezza dell'impulso con correzione di fase e frequenza (Phase and Frequency Correct)

La modalità di modulazione della larghezza di impulso con correzione di fase e frequenza (PWM PFC) (WGMn3-0 = 0b1000 o 0b1001) è progettata per generare impulsi PWM ad alta risoluzione con correzione di fase e frequenza. Proprio come la modalità PWM FC, la modalità PWM FC si basa sul funzionamento bidirezionale del contatore. Il contatore passa dal limite basso (0x0000) al limite alto e poi torna dal limite alto al limite basso. Se viene specificata la modalità PWM non invertente, l'uscita OCnx viene ripristinata se si verifica una corrispondenza tra TCNTn e OCRnx durante il conteggio avanti e viene impostata se si verifica una corrispondenza durante il conteggio indietro. Nella modalità invertita l'operazione è inversa. Il funzionamento bidirezionale, rispetto al funzionamento unidirezionale, è associato alla generazione di frequenze più basse. Tuttavia, a causa della simmetria delle modalità PWM con conteggio bidirezionale, il loro utilizzo è preferibile nelle attività di controllo dell'azionamento.

La differenza principale tra le modalità PWM FC e PWM FC è il momento in cui il registro OCRnx viene aggiornato dal registro buffer OCRnx (vedere Figura 3 e Figura 4).

La risoluzione PWM in questa modalità può essere impostata utilizzando il registro ICRn o OCRnA. La risoluzione minima è 2 bit (ICRn o OCRnA = 0x0003) e la risoluzione massima è 16 bit (ICRn o OCRnA = 0xFFFF). La risoluzione PWM in bit può essere calcolata utilizzando la seguente espressione:

Nella modalità PWM FCC, il contatore viene incrementato finché non corrisponde al valore in ICRn (WGMn3:0 = 0b1000) o in OCRnA (WGMn3:0 = 0b1001). Ciò significa raggiungere l'inizio del conteggio, dopodiché la direzione del conteggio cambia. Il valore di TCNTn rimane all'inizio del conteggio per un ciclo di clock del timer. Il diagramma temporale per la modalità PWM FCC è mostrato nella Figura 54. La figura mostra la modalità PWM FCC quando l'inizio del conteggio è impostato dal registro OCRnA o ICRn. Il valore TCNTn viene mostrato come grafico della funzione per illustrare il conteggio bidirezionale. Il diagramma mostra le uscite PWM sia non invertenti che invertenti. Le brevi linee orizzontali indicano i punti sul grafico TCNTn in cui si verifica una corrispondenza tra OCRnx e TCNTn. Il flag di interruzione OCnx viene impostato dopo che si è verificata una corrispondenza.

Figura 4 – Diagramma temporale della modalità PWM con correzione di fase e frequenza

Il flag di overflow del contatore del timer (TOVn) viene impostato sullo stesso ciclo di clock quando i registri vengono aggiornati con il valore dal registro buffer (al limite di conteggio inferiore). Se il registro OCRnA o ICRn viene utilizzato per impostare il limite superiore, quando il contatore raggiunge il limite superiore, viene impostato rispettivamente il flag OCnA o ICFn. I flag di interruzione possono essere utilizzati per generare un'interruzione quando un contatore raggiunge un limite alto o basso.

Quando si modifica il limite superiore, è necessario assicurarsi che il nuovo valore sia maggiore o uguale ai valori in tutti i registri delle soglie di confronto. Altrimenti, se il limite superiore è impostato su un valore inferiore a uno qualsiasi dei valori nei registri delle soglie di confronto, non si verificherà mai una corrispondenza tra TCNTn e OCRnx.

La Figura 4 mostra che, a differenza della modalità PWM FC, il segnale di uscita generato è simmetrico in tutti i periodi. Poiché i registri OCRnx vengono aggiornati al limite di conteggio inferiore, le durate dei conteggi in avanti e all'indietro sono sempre uguali. Di conseguenza, gli impulsi in uscita hanno una forma simmetrica e, quindi, una frequenza corretta.

Si consiglia di utilizzare il registro ICRn per impostare il limite superiore se il valore del limite superiore è costante. In questo caso, anche il registro OCRnA viene liberato per la modulazione dell'ampiezza degli impulsi sul pin OCnA. Tuttavia, se è necessario modificare dinamicamente la frequenza PWM modificando il limite superiore, si consiglia di utilizzare il registro OCRnA per impostare il limite superiore a causa del suo doppio buffering.

In modalità PWM, le unità di confronto consentono di generare impulsi PWM sul pin OCnx. Se COMnx1:0 = 0b10, allora viene impostata un'uscita PWM non invertente, e se COMnx1:0=0b11, allora un'uscita invertente (vedi tabella 60). Il valore OCnx sarà presente sul pin della porta corrispondente solo se è impostato sulla direzione di uscita. Il segnale PWM viene generato impostando (reimpostando) il registro OCnx su una corrispondenza tra OCRnx e TCNTn durante il conteggio up e reimpostando (impostando) il registro OCnx su una corrispondenza tra OCRnx e TCNTn durante il conteggio indietro. La frequenza PWM in questa modalità con un dato limite superiore (UP) di conteggio viene determinata come segue:

dove N è il fattore di divisione del prescaler (1, 8, 32, 64, 128, 256 o 1024).

La scrittura dei valori limite nel registro OCRnx è associata a casi speciali nella generazione di segnali PWM in questa modalità. Se si imposta OCRnx uguale al limite inferiore (0x0000), in modalità non invertente l'uscita avrà costantemente un livello logico basso e quando si scrive un valore uguale al limite superiore, l'uscita avrà un livello logico alto per un a lungo. Nella modalità di inversione, i livelli indicati saranno opposti.

Se si utilizza OCRnA per impostare il limite superiore (WGMn3:0 = 0b1001) e COMnA1:0 = 0b01, verrà generata un'onda quadra all'uscita OCnA.


L'implementazione hardware di PWM offre indubbi vantaggi rispetto al software, poiché solleva il processore da codice e tempo non necessari e ingombranti per la sua manutenzione e offre anche maggiori opportunità per l'utilizzo del lavoro con PWM. È sufficiente inizializzare il timer/contatore (inserire i valori necessari nei registri utilizzati dal timer/contatore) e il timer/contatore può funzionare indipendentemente dal processore; di conseguenza, il processore può svolgere altri compiti, solo occasionalmente contattando al momento necessario per regolare o modificare la modalità o ottenere risultati dal timer/contatore.

Descrizione dei flag di interruzione

T1 può generare un interrupt quando:

  1. overflow del registro del contatore TCNT1;
  2. se il registro di conteggio TCNT1 e il registro di confronto OCR1A e OCR1B sono uguali (separatamente per ciascun registro);
  3. mentre si memorizza il registro di conteggio nel registro di cattura ICR1.

T2 può generare un interrupt quando:

  1. Overflow del registro del contatore TCNT2;
  2. quando il registro di conteggio TCNT2 e il registro di confronto OCR2 sono uguali.

I flag di tutti gli interrupt si trovano nel registro TIFR e l'abilitazione/disabilitazione degli interrupt si trova nel registro TIMSK.

Bit di registro TIMSK
Registrati7 6 5 4 3 2 1 0
TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0* TOIE0
  • OCIE2- Flag di abilitazione interrupt per l'evento “match” del timer/contatore T2
  • TOIE2- Flag di abilitazione dell'interruzione di overflow del timer/contatore T2
  • TICIE1- Flag di abilitazione interrupt per l'evento “cattura” del temporizzatore/contatore T1
  • OCIE1A- Flag di abilitazione interruzione per l'evento “match A” del timer/contatore T1
  • OCIE1B- Flag di abilitazione interruzione per l'evento “match B” del timer/contatore T1
  • TOIE1- Flag di abilitazione dell'interruzione di overflow del timer/contatore T1
  • OCIE0*- Flag di abilitazione interrupt per l'evento “coincidenza” del timer/contatore T0 (* - non disponibile in ATmega8)
  • TOIE0- Flag di abilitazione interrupt di overflow del timer/contatore T0
  • OCF2- Flag di interruzione per l'evento “coincidenza” del timer/contatore T2
  • TOV2- Flag di interruzione di overflow del timer/contatore T2
  • ICF1- Flag di interruzione per l'evento “cattura” del timer/contatore T1
  • OCF1A- Flag di interruzione per l'evento "coincidenza A" del timer/contatore T1
  • OCF1B- Flag di interruzione per l'evento "coincidenza B" del timer/contatore T1
  • TOV1- Flag di interruzione di overflow del timer/contatore T1
  • OCF0- Flag di interruzione per l'evento “coincidenza” del timer/contatore T0
  • TOV0- Flag di interruzione di overflow del timer/contatore T0

Descrizione del funzionamento del timer/contatore T1 nel controller ATmega8/16

Il timer/contatore a sedici bit T1 può essere utilizzato per generare intervalli di tempo, contare il numero di segnali esterni e generare segnali PWM con cicli di lavoro e durate variabili sui pin OC1A e OC1B. Inoltre, tramite un segnale esterno dal pin ICP1 o da un comparatore analogico, T1 può salvare il suo stato attuale in un registro di cattura separato ICR1.

Bit di registro TCCR1A:TCC1B:TCNT1:OCR1A:OCR1B:ICR1
Registrati7 6 5 4 3 2 1 0
TCCR1A COM1A1 COM1A0 COM1B1 COM1BO FOC1A FOC1B WGM11 WGM10
TCCR1B ICNC1 CIEM1 * WGM13 WGM12 CS12 CS11 CS10
TCNT1:H R/W R/W R/W R/W R/W R/W R/W R/W
TCNT1:L R/W R/W R/W R/W R/W R/W R/W R/W
OCR1A:H R/W R/W R/W R/W R/W R/W R/W R/W
OCR1A:L R/W R/W R/W R/W R/W R/W R/W R/W
OCR1B:H R/W R/W R/W R/W R/W R/W R/W R/W
OCR1B:L R/W R/W R/W R/W R/W R/W R/W R/W
ICR1:H R/W R/W R/W R/W R/W R/W R/W R/W
ICR1:L R/W R/W R/W R/W R/W R/W R/W R/W

Ciascun registro a 16 bit si trova fisicamente in due registri a 8 bit, quindi quando si legge una voce in essi devono essere eseguite due operazioni. In scrittura viene caricato prima il byte alto e poi quello basso; in lettura, invece, viene letto prima il byte basso e poi quello alto.

TCCR1A:TCCR1B- Registri di controllo timer/contatore a 8 bit T1

TCNT1- Registro timer/contatore a 16 bit T1. A seconda della modalità operativa, il contenuto di questo registro viene cancellato, incrementato (il valore viene aumentato di 1) o decrementato (il valore viene diminuito di 1) per ciascun impulso del segnale di clock del timer/contatore.

OCR1A:OCR1B- Registri di confronto a 16 bit

ICR1- Registro di cattura a 16 bit, memorizza il valore di TCNT1 quando un fronte di segnale attivo viene applicato al pin ICP1 o da un segnale proveniente dal comparatore.

Assegnazione dei bit

COM1A1:COM1A0:COM1B1:COM1B0- Questi bit determinano il comportamento del pin OC1A:OC1B quando il valore del registro di conteggio TCNT1 e del registro di confronto OCR1A:OCR1B corrispondono

FOC1A:FOC1B- Questi bit vengono utilizzati per forzare un cambiamento nello stato del pin OC1A:OC1B

ICNC1- Bit di controllo del circuito di interferenza, se il bit è “0” la cattura avverrà sul primo fronte attivo, se “1” la cattura avverrà dopo il quarto campione identico del segnale di cattura.

CIEM1- Bit per la selezione del fronte attivo del segnale, se il suo valore è “0”, il salvataggio del registro di conteggio TCNT1 nel registro di cattura OCR1 sarà sul fronte di discesa del segnale, se “1” sul fronte di salita.

WGM13:WGM12:WGM11:WGM10- Questi bit determinano la modalità operativa del temporizzatore/contatore T1

CS22:CS21:C20- Bit che determinano la sorgente del segnale del timer/contatore T1.

Selezione della modalità di funzionamento del timer/contatore T1
WGM13WGM12WGM11WGM10Modalità operativaModulo Conto (IN ALTO)
0 0 0 0 Normale $FFFF
0 0 0 1 PWM con correzione di fase

8 bit

$ 00 FF
0 0 1 0 PWM con correzione di fase

9 bit

$ 01FF
0 0 1 1 PWM con correzione di fase

10 bit

$ 03FF
0 1 0 0 CTC (reimpostato in corrispondenza) OCR1A
0 1 0 1 PWM veloce

8 bit

$ 00 FF
0 1 1 0 PWM veloce

9 bit

$ 01FF
0 1 1 1 PWM veloce

10 bit

$ 03FF
1 0 0 0 ICR1
1 0 0 1 PWM corretto di fase e frequenza OCR1A
1 0 1 0 PWM con correzione di fase ICR1
1 0 1 1 PWM con correzione di fase OCR1A
1 1 0 0 CTC (reimpostato in corrispondenza) ICR1
1 1 0 1 Riservato *
1 1 1 0 PWM veloce ICR1
1 1 1 1 PWM veloce OCR1A

Selezione di una sorgente di orologio

Modalità normale

La modalità operativa più semplice è T1. Per ogni impulso del segnale di clock il registro di conteggio TCNT1 viene incrementato (il valore aumenta di 1). Quando si passa attraverso il valore $FFFF del modulo di conteggio (TOP), si verifica un overflow e il ciclo di clock successivo inizia a contare dal valore $0000, nello stesso momento viene impostato il flag TOV1=1 nel registro TIFR e può essere generato un interrupt. essere generato se il flag TOIE1=1 è impostato nel registro TIMSK. Per generare un segnale di una determinata frequenza in questa modalità, è necessario scrivere i bit COM1A1=0:COM1A0=1 per l'uscita OC1A o COM1B1=0:COM1B0=1 per l'uscita OC1B del controller.

Inoltre, per ogni ciclo di clock, viene effettuato un confronto tra il registro di conteggio TCNT1 e il registro di confronto OCR1A:OCR1B; se c'è corrispondenza viene impostato il flag di interrupt OCF1A=1:OCF1B=1 e se il bit OCIE1A=1 :OCIE1B=1 del registro TIMSK, viene generato un interrupt. Allo stesso tempo, lo stato del pin OC1A:OC1B può essere modificato a seconda delle impostazioni dei bit COM1A1:COM1A0:COM1B1:COM1B0.

Modalità CTC (reset in corrispondenza)

In questa modalità, T1 funziona secondo lo stesso principio della modalità Normale. La differenza è che il valore massimo possibile del registro di conteggio TCNT1 è limitato dal valore del registro di confronto OCR1A o ICR1 (vedere la tabella di selezione della modalità timer/contatore). Quando TCNT1 raggiunge il valore di OCR1A o ICR1, il valore di TCNT1 viene reimpostato su TCNT1=$ 0000. Allo stesso tempo, viene impostato il flag TOV1=1 COM1A1:COM1A0:COM1B1:COM1B0 Determina il comportamento del pin OC1A:OC1B quando c'è una corrispondenza.

Modalità PWM veloce (PWM veloce)

Utilizzando questa modalità, è possibile generare un segnale PWM ad alta frequenza. Il principio e la procedura di funzionamento non differiscono dalla modalità Normale, ad eccezione della presenza del doppio buffering del registro OCR1A:OCR1B, che elimina la comparsa di impulsi di segnale asimmetrici e differisce anche nel comportamento dei pin OC1A:OC1B ( Vedi la tabella).


Modalità PWM con correzione di fase

La differenza tra questa modalità e le precedenti è che il registro di conteggio funziona come un contatore inverso. Poiché questa modalità è consigliata da Atmel come la più adatta per la messa a punto dei motori, la considereremo in modo più dettagliato. Quando il registro di conteggio TCNT1 raggiunge il valore del modulo di conteggio (TOP) (o il valore del registro ICR1 o il valore del registro OCR1A, vedere la tabella di selezione della modalità timer/contatore), la direzione di conteggio cambia. Quando il registro di conteggio TCNT1 raggiunge il valore minimo ($0000), cambia anche la direzione di conteggio e contemporaneamente viene impostato il flag di interrupt TOV1 del registro TIFR. Inoltre, se il contenuto del registro di conteggio TCNT1 e del registro di confronto OCR1A:OCR1B è uguale, viene impostato il flag OCF1A:OCF1B del registro TIFR e lo stato dell'uscita OC1A:OC1B cambia, secondo la tabella.

Per evitare emissioni asimmetriche durante la scrittura di un valore nel registro OCR1A:OCR1B, in questa modalità viene implementato il doppio buffer di scrittura. Grazie a ciò, la variazione effettiva del valore del registro cambia nel momento in cui il registro del contatore TCNT1 raggiunge il valore del modulo di conteggio (TOP) (o il valore del registro ICR1 o il valore del registro OCR1A, vedere la selezione della modalità timer/contatore tavolo). Pertanto, all'inizio, quando il timer/contatore viene inizializzato, il pin OC1A:OC1B non cambierà il suo stato in seguito alla corrispondenza finché il registro non raggiunge il valore (TOP).


Compito: Sviluppiamo un programma per controllare la luminosità di una lampada a incandescenza da 12 Volt utilizzando PWM. Quando si preme il pulsante "Altro", la luminosità della lampada aumenta e quando si fa clic sul pulsante "Meno", la luminosità diminuisce. Lo schema del nostro futuro dispositivo è mostrato in figura. Come al solito, utilizziamo il microcontrollore Atmega8, che sarà sincronizzato da un oscillatore interno con una frequenza di 4 MHz. In realtà, otterremo un dimmer: questi dispositivi sono progettati per regolare la luminosità degli apparecchi di illuminazione. Al giorno d'oggi, i dimmer LED sono i più diffusi.

Per semplicità potete collegare anche un led al nostro circuito, ma con una lampadina sarà più chiaro. I pulsanti sono collegati ai pin PD0, PD1. Colleghiamo il carico all'uscita PB1(OC1A) attraverso un resistore e un transistor ad effetto di campo MOSFET, che funzionerà come chiave per noi (in modalità commutazione). Un transistor ad effetto di campo è preferibile perché il suo gate è isolato dal circuito di alimentazione ed è controllato da un campo elettrico e la corrente di controllo raggiunge i microampere. Ciò consente, utilizzando uno o due transistor, di controllare un carico di enorme potenza (fino a decine di ampere e decine o centinaia di volt) senza caricare il microcontrollore. Tenendo conto anche del fatto che i transistor ad effetto di campo possono essere collegati in parallelo (a differenza di quelli bipolari), è possibile ottenere una cascata ancora più potente di centinaia di ampere.

Ora scopriamo come il microcontrollore implementa PWM e scriviamo un programma. Come accennato in precedenza, il nostro MK ha 3 timer e tutti possono funzionare in modalità PWM. Lavoreremo con un timer/contatore a sedici bit. Bit WGM13-10 configuriamo il nostro timer per funzionare FastPWM con un limite di conteggio superiore ICR1. Il principio del programma è questo: il nostro timer conta da 0 a 65535(0xFFFF), nel registro ICR1 Inseriamo il numero 255, questo sarà il limite superiore del conteggio del timer (TOP), la frequenza del segnale PWM sarà costante. Inoltre, il nostro timer è configurato in modo tale che se il registro di conteggio e il registro di confronto corrispondono (TCNT1 = OCR1A), l'uscita del controller commuterà OC1A. Il ciclo di lavoro PWM può essere modificato scrivendo nel registro di confronto OCR1A un certo numero da 0 a 255, maggiore è questo numero, maggiore è il fattore di riempimento, più luminosa brucerà la lampada. A seconda del pulsante premuto, la variabile cambia io, e poi viene scritto nel registro OCR1A.

Di seguito è riportato il testo completo del programma. I commenti descrivono più dettagliatamente il funzionamento del programma.

/***Lezione n.8. Generazione di segnali PWM***/ #include #includere int main(void) ( unsigned int i=0; //definisce la variabile i /***Configurazione delle porte I/O***/ PORTB = 0x00; DDRB |= (1<< PB1); PORTD |= (1 << PD1)|(1 << PD0); // подключаем внутренние нагрузочные резисторы DDRD = 0x00; /***Настройка таймера***/ TCCR1A |= (1 << COM1A1)|(0 << COM1A0) // Установим биты COM1A1-COM1A0:0b10, означает сброс вывода канала A при сравнении |(1 << WGM11)|(0 << WGM10); // Установим биты WGM13-10:0b1110, согласно таблице это TCCR1B |= (1 << WGM13)|(1 << WGM12) // будет режим - FAST PWM, где верхний предел счета задается битом ICR1 |(0 << CS12)|(0 << CS11)|(1 << CS10); // Битами CS12-10:0b001 задаем источник тактового сигнала для таймера МК, включен без делителя TCNT1 = 0x00; // начальная установка счетчика ICR1 = 0xFF; // задаем период ШИМ, здесь у нас число 255, // по формуле fPWM=fclk_I/O/N*(1+ICR1)// вычисляем частоту ШИМ, она будет равна 15625 Hz OCR1A = 0x00; // начальный коэффициент заполнения ШИМ /***Основной цикл программы***/ while(1) { if((PIND&(1 << PD0)) == 0) //если кнопка "больше" нажата { if (i < 254) { // коэффициент заполнения ШИМ изменяется от 0 до 255 i=i+1; // увеличиваем i на единицу OCR1A = i; // записываем переменную в регистр сравнения _delay_ms(30); // задержка 30ms } } if((PIND&(1 << PD1)) == 0) //если кнопка "меньше" нажата { if (i >0) // Il ciclo di lavoro PWM cambia da 255 a 0 ( i--; // diminuisce i di uno (puoi anche scriverlo) OCR1A = i; // scrive una variabile nel registro di confronto _delay_ms(30); // ritardo 30ms ) ) )

Attenzione! Innanzitutto, forniamo alimentazione al microcontrollore, quindi è necessario assicurarsi che il transistor sia collegato al pin MK e solo successivamente alimentare il circuito con la lampada e il transistor ad effetto di campo. Altrimenti potresti bruciare il transistor. Il fatto è che quando sono spente, le "gambe" dell'MK "penzolano nell'aria" - non sono collegate a nulla e su di esse si verificano interferenze. Queste deboli interferenze sono sufficienti per aprire parzialmente un transistor ad effetto di campo molto sensibile. Quindi la sua resistenza tra drain e source scenderà da diversi MOhm a diversi Ohm o frazioni di Ohm e una grande corrente fluirà attraverso di esso fino alla lampada. Ma il transistor non si aprirà completamente, perché per questo è necessario applicare al gate non un'interferenza di 1-3 V, ma 5 V stabili, e la sua resistenza sarà molto maggiore del minimo. Ciò porterà al rilascio di una grande quantità di calore su di esso e fumerà e forse brucerà.

Temporizzatori PWM (lezione)

Ovviamente, abbiamo bisogno di una sorta di contatore esterno che funzioni indipendentemente dal funzionamento del processore e che il processore possa vedere in qualsiasi momento cosa sta ticchettando. Oppure affinché il contatore generi eventi di overflow o underflow: alza il flag o genera un'interruzione. E il processore lo vedrà e lo elaborerà. E esiste un contatore del genere, nemmeno uno: questi sono timer periferici. Un AVR può averne diversi con diverse profondità di bit. ATmega16 ne ha tre, ATmega128 ne ha quattro. Inoltre, un timer può essere più di un semplice contatore; un timer è uno dei dispositivi periferici più multifunzionali (in termini di funzioni alternative).

Cosa possono fare i timer

· Funziona dal quarzo esterno a 32768 Hz

· Genera diversi tipi di segnale PWM

· Emetti interruzioni (una mezza dozzina di eventi diversi) e imposta flag

Sorgente del segno di spunta del timer

Il timer/contatore (di seguito denominato TC) conta gli impulsi di clock provenienti dal generatore di clock integrato o dall'ingresso di conteggio. Con le impostazioni appropriate, il veicolo conterà il fronte di salita (fronte da 0-1) o il fronte di uscita (fronte di 1-0) degli impulsi che arrivano agli ingressi. La cosa principale è che la frequenza degli impulsi in arrivo non supera la frequenza dell'orologio del processore, altrimenti non avrà il tempo di elaborare gli impulsi.

Inoltre, alcuni timer sono in grado di funzionare in modalità asincrona. Cioè, il TS non conta gli impulsi di clock del processore, ma gli impulsi del proprio generatore, alimentato da un quarzo separato. A tale scopo il veicolo dispone di ingressi separati sui quali è possibile collegare un risuonatore al quarzo. Perché è necessario? Almeno per organizzare un orologio in tempo reale. Ho appeso un orologio al quarzo su di loro a 32768 Hz e puoi misurare il tempo: si verificheranno 128 overflow al secondo (se il veicolo è a otto bit). Quindi un overflow è 1/128 di secondo. Inoltre, il timer non si ferma durante l'elaborazione dell'interruzione di overflow ma continua anche a contare.

Predivisore

Se il timer conta gli impulsi provenienti dal generatore di clock o da quello interno, è comunque possibile farli passare attraverso un prescaler. Cioè, anche prima di entrare nel registro di conteggio, la frequenza degli impulsi verrà divisa. Puoi dividere per 8, 32, 64, 128, 256, 1024. Quindi, se appendi un orologio al quarzo sul veicolo e lo fai passare attraverso il prescaler per 128, il timer conterà alla velocità di una volta al secondo. È anche conveniente utilizzare un prescaler quando è necessario ottenere solo un intervallo ampio e l'unica fonte di conteggio è il generatore di clock del processore e il conteggio di questi megahertz è difficile, ma se lo si passa attraverso un prescaler, tutto è più semplice . Tuttavia, se si esegue un TS con un prescaler, il primo tick non arriverà necessariamente al registro di conteggio dopo il numero di impulsi richiesto.

Dipende in che stato si trovava il prescaler, e se al momento dell'accensione avesse già contato quasi fino al valore impostato? Ciò significa che ci sarà immediatamente un segno di spunta. Il prescaler funziona sempre, indipendentemente dal fatto che il timer sia acceso o meno. Pertanto, i prescaler possono e devono essere reimpostati. È inoltre necessario tenere conto del fatto che il prescaler è lo stesso per tutti i contatori, pertanto, quando lo si ripristina, è necessario tenere conto del fatto che un altro timer avrà un ritardo fino al segno di spunta successivo.

Ad esempio, il primo timer opera sul pin 1:64 e il secondo sul pin 1:1024 del prescaler. Il secondo ha quasi raggiunto 1024 nel prescaler e ora dovrebbe esserci un segno di spunta del timer, ma poi sei andato a reimpostare il prescaler per avviare il primo timer esattamente da zero. Cosa accadrà? Per il secondo, il divisore verrà immediatamente ripristinato a 0 (il prescaler è lo stesso, ha un registro) e il secondo timer dovrà attendere altri 1024 cicli di clock per ottenere un impulso! E se reimpostate il prescaler nel ciclo, a beneficio del primo timer, più spesso di una volta ogni 1024 cicli di clock, il secondo timer non funzionerà mai. Per resettare i prescaler è sufficiente scrivere il bit PSR10 nel registro SFIOR. Il bit PSR10 verrà ripristinato automaticamente al successivo ciclo di clock.

Registro dei conti

L'intero conteggio viene accumulato nel registro di conteggio TCNTx, dove x è il numero del timer. Può essere a 8 o 16 bit, nel qual caso è costituito da due registri TCNTxH e TCNTxL: rispettivamente il byte alto e quello basso.

E qui c'è un problema. E il punto è che il timer conta indipendentemente dal processore, quindi possiamo mettere prima un byte, inizierà a contare, poi il secondo e il ricalcolo inizierà tenendo conto del secondo byte. Il timer è un dispositivo preciso, quindi i suoi registri di conteggio devono essere caricati contemporaneamente! Ma come? E gli ingegneri di Atmel hanno risolto il problema in modo semplice: la scrittura nel registro alto (TCNTxH) viene prima eseguita nel registro TEMP. Questo registro è puramente ufficiale e non ci è in alcun modo accessibile.

Qual'è il risultato? Scriviamo il byte alto nel registro TEMP (per noi è ancora TCNTxH), quindi scriviamo il byte basso. In questo momento il valore precedentemente registrato viene inserito nel TCNTxH reale. Cioè, due byte, alto e basso, vengono scritti contemporaneamente! Non è possibile modificare l'ordine! Sembra questo:

Perché disabilitare gli interrupt? Sì, in modo che dopo aver scritto il primo byte, il programma non esca accidentalmente senza interruzioni.

Tutto viene letto allo stesso modo, solo in ordine inverso. Prima il byte basso (con il byte alto in TEMP), poi il byte alto. Ciò garantisce che stiamo contando esattamente il byte attualmente presente nel registro di conteggio.

Registri di controllo

La funzione principale del timer è il conteggio. Il registro principale è TCCRx. Per TC0 è TCCR0, per gli altri timer TCCR N rispettivamente. I primi 3 bit di questo registro: CSx2..CSx0 sono responsabili dell'impostazione del prescaler e della sorgente del segnale di clock; al posto di x, viene sostituito il numero del timer. I diversi timer sono leggermente diversi, quindi descriveremo i bit CS02...CS00 solo per il timer0.

· 000 - timer fermo

· 001 - il prescaler è uguale a 1, cioè disattivato. Il timer conta gli impulsi dell'orologio

· 010 - il prescaler è 8, la frequenza del clock è divisa per 8

· 011 - il prescaler è 64, la frequenza del clock è divisa per 64

· 100 - il prescaler è 256, la frequenza del clock è divisa per 256

· 101 - il prescaler è 1024, la frequenza del clock è divisa per 1024

· 110 - gli impulsi di clock provengono dal pin T0 alla transizione da 1 a 0

· 111 - gli impulsi di clock provengono dal pin T0 alla transizione da 0 a 1

Interrompe

Ogni evento hardware ha un'interruzione e il timer non fa eccezione. Non appena si verifica un overflow o un altro evento, viene immediatamente generato un interrupt. I registri TIMSK e TIFR sono responsabili delle interruzioni dei timer. E i potenti AVR, come ATMega128, hanno anche ETIFR ed ETIMSK, una sorta di continuazione, poiché lì ci sono più timer.TIMSK è un registro di maschera. Cioè, i bit in esso contenuti abilitano localmente gli interrupt. Se il bit è impostato, l'interrupt specifico è abilitato. Se il bit è zero, questo interrupt non viene elaborato. Per impostazione predefinita, tutti i bit sono zero. I seguenti bit sono responsabili dell'interruzione di overflow:

· TOIE - permesso di interrompere in caso di overflow del timer 0

· TOIE1 - autorizzazione all'interruzione in caso di overflow del timer 1

· TOIE2 - permesso di interrompere in caso di overflow del timer 2

Il registro TIFR è direttamente un registro di bandiera. Quando viene attivato un interrupt, viene impostato il flag di interruzione. Questo flag viene ripristinato dall'hardware quando il programma lascia il vettore. Se gli interrupt sono disabilitati, il flag rimarrà lì finché gli interrupt non saranno abilitati e il programma passerà all'interrupt. Per evitare che ciò accada, il flag può essere ripristinato manualmente. Per fare ciò, devi scriverci 1 in TIFR!

Maggiori informazioni sul timer A TMEGA128sarà discusso più tardi.

Modulazione dell'ampiezza dell'impulso

Modulazione dell'ampiezza dell'impulso ( PWM - Modulazione della larghezza dell'impulso) questo è un modo per specificare un segnale analogico metodo digitale , cioè, da un'uscita digitale che fornisce solo zero e uno, è possibile ottenere valori che cambiano gradualmente. E il punto è:

Immagina un volano pesante che puoi ruotare con un motore. Inoltre, puoi accendere o spegnere il motore. Se lo accendi costantemente, il volano girerà fino al suo valore massimo e continuerà a girare. Se lo spegni, si fermerà a causa delle forze di attrito. Ma se il motore viene acceso per dieci secondi ogni minuto, il volano girerà, ma non alla massima velocità: l'elevata inerzia attenuerà gli strappi derivanti dall'accensione del motore e la resistenza dell'attrito non gli consentirà di girare indefinitamente. Più Durata ON motore al minuto, più velocemente girerà il volano.

A PWM inviamo un segnale all'uscita composto da livelli alto e basso (applicabile alla nostra analogia: accendiamo e spegniamo il motore), cioè zero e uno. E poi tutto questo passa attraverso una catena di integrazione (per analogia, un volano). Per effetto dell'integrazione l'uscita avrà un valore di tensione pari all'area sotto gli impulsi.Mutevole ciclo di lavoro(il rapporto tra la durata del periodo e la durata dell'impulso) è possibile modificare agevolmente quest'area e quindi la tensione di uscita. Pertanto, se l'uscita è 1 s fisso, l'uscita sarà una tensione di alto livello (ad esempio, 12 volt), se zero, allora zero. E se il 50% delle volte il livello è alto e il 50% basso, allora 6 volt. La catena integrante qui sarà la massa dell'armatura del motore, che ha un'inerzia abbastanza grande.

Cosa succede se prendi e dai PWM- il segnale non va da zero al massimo, ma da meno a più. Diciamo da +12 a -12. E puoi impostare un segnale variabile! Quando l'ingresso è zero, l'uscita è -12V, quando ce n'è uno, quindi +12V. Se il ciclo di lavoro è del 50%, l'uscita è 0 V. Se il ciclo di lavoro viene modificato secondo una legge sinusoidale dal massimo al minimo, otteniamo una tensione alternata. E se prendi tre di questi generatori PWM e guidi le sinusoidi attraverso di essi, spostati di 120 gradi l'uno dall'altro, otteniamo la tensione trifase più comune, il che significa ciao motori asincroni e sincroni brushless . Tutti i moderni azionamenti CA industriali sono costruiti secondo questo principio. Una catena RC può essere utilizzata come circuito integratore di livellamento in PWM:

Implementazione hardware del PWM

Quando ATMega Il modo più semplice per farlo è utilizzare il generatore PWM, integrato nei timer. Inoltre, il primo timer ha due canali. Quindi ATmega può implementare quattro canali contemporaneamente PWM.

Il timer ha un registro di confronto speciale OCR. Quando il valore nel registro del contatore del timer raggiunge il valore nel registro di confronto, possono verificarsi i seguenti eventi hardware:

· Interruzione per coincidenza

· Modifica dello stato dell'uscita del confronto esterno O.C..

Le uscite di confronto vengono instradate all'esterno verso i pin del microcontrollore. Supponiamo che PWM- il generatore è configurato così che quando il valore nel registro di conteggio è maggiore, rispetto al registro di confronto, l'output è 1 e quando è inferiore, allora 0. Cosa succederà? Il timer conterà come dovrebbe, da zero a 256 con una frequenza, che configureremo con i bit del prescaler del timer. Dopo l'overflow, viene reimpostato su 0 e continua a contare nuovamente.

All'uscita compaiono degli impulsi. Se si aumenta il valore nel registro di confronto, l'ampiezza dell'impulso si restringerà. Cioè, modificando il valore nel registro di confronto, è possibile modificare il ciclo di lavoro PWM- segnale. E se passi questo segnale PWM attraverso una catena RC di livellamento (integratore), quindi otteniamo un segnale analogico.

Un timer può avere un numero qualsiasi di registri di confronto. Dipende dal modello MK e dal tipo di timer. I nuovi AVR hanno anche tre registri di confronto per timer, che consentono a un MK di organizzare molti canali PWM indipendenti. Esistono diverse modalità PWM stesse:

BSLinea PWM (PWM veloce)

In questa modalità il contatore conta da zero a 255 , una volta raggiunto l'overflow, viene azzerato e il conteggio ricomincia. Quando il valore nel contatore raggiunge il valore del registro di confronto, l'uscita corrispondente OSxx si resetta a zero. Quando il contatore viene ripristinato, questo pin viene impostato su 1.

La frequenza del segnale PWM risultante viene determinata semplicemente: la frequenza del processore è, ad esempio, 8 MHz, il timer segna 256 con una frequenza di clock. Ciò significa che un periodo PWM sarà pari a 8000.000/256 = 31250Hz. Non sarà più veloce: questa è la velocità massima interna 8 MHz generatore di orologi. È ancora possibile aumentare la risoluzione portando il conteggio a 8, 9, 10 bit (se la profondità di bit del timer lo consente), ma bisogna tenere conto che aumentando la profondità di bit, insieme all'aumento della discrezione dell'uscita analogica segnale, riduce drasticamente la frequenza PWM.

PWM con correzione di fase (Phase Correct PWM)

PWM con fase precisa. Funziona in modo simile, ma qui il contatore conta in modo leggermente diverso. Prima da 0 a 255, poi da 255 a 0. Il pin OCxx viene resettato alla prima corrispondenza e impostato alla seconda. Ma la frequenza PWM allo stesso tempo si riduce della metà a causa del periodo più lungo. Il suo scopo principale è creare segnali PWM multifase, ad esempio un'onda sinusoidale trifase. Quelli. i centri degli impulsi in canali diversi e con cicli di lavoro diversi coincideranno.


Riso. Modalità PWM veloce e PWM con correzione di fase

Per evitare impulsi non necessari, qualsiasi valore entra nel registro di confronto attraverso un registro buffer e viene inserito solo quando il valore nel contatore raggiunge il suo massimo. Quelli. all'inizio di un nuovo periodo PWM impulso.

RipristinaDicoincidenza(Cancella timer al confronto)

Reimposta durante il confronto. Molto probabilmente si tratta di PFM, un segnale simulato a frequenza di impulsi. Funziona in modo leggermente diverso qui rispetto ad altre modalità. Qui il timer di conteggio non scorre da 0 al limite, ma da 0 al registro di confronto! E poi si resetta.

Di conseguenza, gli impulsi di uscita hanno sempre lo stesso ciclo di lavoro, ma di frequenze diverse. E molto spesso questa modalità viene utilizzata quando è necessario contare i periodi con un timer (e generare un'interruzione) con la precisione specificata.


Ad esempio, abbiamo bisogno di un'interruzione ogni millisecondo. E per essere sicuro. Come è possibile farlo più facilmente? Attraverso la modalità STS! Lascia che la frequenza sia 8 MHz. Il prescaler sarà pari a 64, quindi la frequenza di conteggio del timer sarà 125000 Hz. E abbiamo bisogno di un'interruzione con una frequenza di 1000 Hz. Pertanto, impostiamo un'interruzione in coincidenza con il numero 125. Quando il conteggio raggiunge 125, l'interruzione viene attivata e il contatore viene azzerato. Raggiunto 125 - ha dato un'interruzione, azzerato.

Contatore temporizzato a 8 bit 0 con funzioni PWM e clock asincrono

Il contatore temporizzatore 0 è un modulo contatore temporizzatore multifunzionale a 8 bit a canale singolo con un'uscita hardware per la generazione di un segnale PWM e un generatore di orologio asincrono opzionale integrato, ottimizzato per l'uso del quarzo dell'orologio (32768 Hz) per timbratura asincrona rispetto alla sincronizzazione del sistema.




Registri

Registro contatore-temporizzatore (TCNT0) e registro di confronto delle soglie (OCR0) - 8 bit. registri. I segnali di richiesta di interruzione sono rappresentati come flag di interruzione del timer nel registro TIFR. Tutti gli interrupt vengono mascherati individualmente utilizzando il timer Interrupt Mask Register (TIMSK). Il timer-contatore può essere cronometrato internamente tramite il prescaler o in modo asincrono tramite i pin TOSC1/2 esterni. Il funzionamento asincrono è controllato dal registro ASSR. Il blocco orologio seleziona quale sorgente orologio viene utilizzata. Se la sorgente dell'orologio non è specificata, il contatore del timer è in uno stato inattivo. L'uscita clkT0 è l'uscita della logica di selezione della temporizzazione.Il valore del registro della soglia di confronto a doppio buffer (OCR0) viene continuamente confrontato con il valore del contatore del temporizzatore. Il risultato del confronto può essere utilizzato per generare segnali PWM o ad onda quadra a frequenza variabile sul pin OC0. Se la soglia del confronto corrisponde al valore del contatore del temporizzatore, viene impostato il flag del risultato del confronto (OCF0), che può essere utilizzato per generare una richiesta di interruzione in base al risultato del confronto.

NP (limite inferiore)

Il contatore raggiunge lo zero (0x00)

MAX (valore massimo)

Il contatore raggiunge un valore massimo di 0xFF (decimale 255)

VP (limite superiore)

Il contatore raggiunge il limite di conteggio superiore (count top). La parte superiore del conteggio può essere il valore fisso 0xFF o il contenuto del registro OCR0.

Sorgenti orologio timer-contatore 0

TC0 può essere sincronizzato internamente in modo sincrono o esternamente in modo asincrono (rispetto all'orologio interno del sistema). Il valore predefinito è clkT0, che equivale a clkI/O. Se viene scritto "1" nel bit AS0 del registro ASSR, il generatore sui pin TOSC1 e TOSC2 funge da sorgente.

Controblocco

La base di TC0 è un contatore bidirezionale programmabile.


Descrizione dei segnali (segnali interni):

Conteggio: incrementa o decrementa TCNT0 di 1.

Direzione: imposta la direzione del conteggio: (+1, conteggio in avanti) o (-1, conteggio all'indietro).

Reset: reimposta il contenuto di TCNT0 (scrivendo 0 su tutti i bit).

clkT0 - Sincronizzazione timer-contatore.

Limite superiore: imposta il valore massimo su TCNT0.

Limite inferiore: imposta il valore minimo su TCNT0 (0) .

A seconda della modalità operativa selezionata, il contatore viene azzerato, incrementato o decrementato ad ogni ciclo di clock clkT0. Il segnale di clock clkT0 può essere interno o esterno e la sua frequenza viene selezionata utilizzando i bit CS02-CS00. Se la sorgente di sincronizzazione non è specificata (CS02-CS00=0b000), il timer si ferma. Lo stato TCNT0 è disponibile per la CPU indipendentemente dalla temporizzazione.La sequenza di conteggio viene determinata impostando i bit WGM01 e WGM00 dal registro TCCR0. Esiste una relazione precisa tra il comportamento del contatore e la forma d'onda generata all'uscita OC0. Il flag di overflow TC (TOV0) viene impostato in base alla modalità operativa, selezionata dai bit WGM01, WGM00. Il bit TOV0 può essere utilizzato per generare un interrupt della CPU.

Blocco di confronto

Il comparatore digitale a 8 bit confronta continuamente il contenuto del registro del contatore temporizzatore TCNT0 con il registro della soglia di confronto OCR0. Ogni volta che il valore di TCNT0 corrisponde al valore di OCR0, il comparatore imposta il flag di corrispondenza OCF0 al successivo tick dell'orologio del timer. Se l'interruzione è abilitata con il bit OCIE0=1, l'impostazione del flag di corrispondenza provoca una richiesta di interruzione. Il flag OCF0 viene cancellato automaticamente durante l'elaborazione dell'interruzione. Il generatore di segnale utilizza il segnale del risultato del confronto per generare impulsi rettangolari secondo uno degli algoritmi, che viene selezionato dai bit di impostazione della modalità operativa del timer WGM01, WGM00 e dai bit di impostazione della modalità di generazione del segnale di uscita (COM01, COM00). I limiti di conteggio superiore e inferiore vengono utilizzati in alcune modalità operative per eseguire azioni speciali.

Il registro OCR0 è implementato utilizzando uno schema di doppio buffering quando si utilizzano le modalità PWM (modulazione di larghezza di impulso). Nelle modalità normale e CTC, il circuito del doppio buffering è disabilitato. Il doppio buffering consente di sincronizzare l'aggiornamento del registro di confronto OCR0 quando viene raggiunto il limite di conteggio superiore o inferiore. Questa sincronizzazione impedisce la possibilità di generare impulsi PWM sbilanciati di lunghezze dispari, garantendo così che la generazione dell'onda quadra non fallisca.L'accesso al registro OCR0 può sembrare complicato, ma c'è un motivo. Una volta abilitato il doppio buffering, la CPU accede al registro del buffer OCR0 e, quando disabilitato, accede direttamente al registro OCR0.

Forzare il risultato del confronto

Nelle modalità di generazione di impulsi senza PWM nel formatore di impulsi, il risultato del confronto può essere impostato direttamente tramite il bit FOC0. Forzare il risultato del confronto del comparatore non imposta il flag OCF0 né reimposta/riavvia il timer, ma influenza lo stato del pin OC0, che verrà impostato, cancellato o commutato (invertito) a seconda dell'impostazione selezionata di COM01, Bit COM00. Questa funzione permette di impostare il registro OCR0 allo stesso valore di TCNT0 senza generare una richiesta di interrupt se l'orologio del timer-contatore è abilitato.

Utilizzando un blocco di confronto

Poiché la scrittura su TCNT0 blocca qualsiasi azione basata sul risultato del confronto per un ciclo di sincronizzazione del timer, indipendentemente dalla modalità operativa, quando si cambia TCNT0 quando si utilizza il canale di confronto (indipendentemente dal fatto che la sincronizzazione del timer funzioni o meno), è necessario tenere in considerazione le seguenti caratteristiche. Se nel registro TCNT0 viene scritto un valore uguale a OCR0, ignorare la corrispondenza comporterà la generazione di una forma d'onda errata. Per analogia, si dovrebbe evitare di scrivere un valore pari al limite inferiore (0x00) su TCNT0 se il contatore funziona come contatore sottrattivo. L'impostazione di OC0 deve essere eseguita prima di impostare la linea I/O da inviare nel registro di direzione.

Blocco di generazione del segnale di uscita

I bit di impostazione della modalità di generazione del segnale di uscita (COM01:0) hanno un duplice scopo. Da un lato i bit COM01, COM00 vengono utilizzati dal condizionatore di segnale e determinano quale stato logico dovrebbe trovarsi sull'uscita OC0 quando si verifica la successiva corrispondenza. D'altra parte, i bit COM01, COM00 vengono utilizzati per abilitare/disabilitare la funzione di uscita alternativa della porta OC0. La figura mostra uno schema logico semplificato interessato dai bit COM01, COM00. P Vengono forniti solo i registri di controllo della porta I/O (DDR e PORT) che sono influenzati dai bit COM01, COM00.


La funzione di linea della porta I/O universale è sostituita dalla funzione di uscita del condizionatore di segnale OC0 se almeno uno dei bit COM01, COM00 è uguale a 1. Tuttavia, il controllo della direzione di uscita di OC0 (ingresso o uscita) in questo caso rimane con il bit corrispondente del registro di direzione dati della porta B (DDRB.4). Affinché sul pin OC0 sia presente il valore del registro OC0 è necessario configurare questa linea come uscita (impostare il bit DDRB.4). Il controllo dell'ingresso della funzione alternativa è indipendente dalla modalità di generazione del segnale.

Modi operativi del timer-contatore 0

Modalità operativa timer, incl. Il comportamento del timer-contatore e dell'uscita del condizionatore di segnale associato è impostato da una combinazione di bit che specificano la modalità operativa del timer (WGM01, WGM00) e la modalità di generazione del segnale di uscita (COM01, COM00). In questo caso, i bit per l'impostazione della modalità di generazione del segnale di uscita non influiscono sull'algoritmo di conteggio, perché L'algoritmo di conteggio dipende solo dallo stato dei bit di impostazione della modalità timer. Nelle modalità con PWM, i bit COM01, COM00 consentono di abilitare/disabilitare l'inversione sull'uscita PWM generata (ovvero selezionare PWM con inversione o PWM senza inversione). Per le modalità non PWM, i bit COM01:0 determinano quale azione deve essere intrapresa quando viene soddisfatta la condizione di confronto: resettare, impostare o invertire l'uscita.

Le modalità operative del timer sono state descritte sopra (normale (conteggio), ripristino coincidente, PWM veloce e PWM con correzione di fase).

Funzionamento asincrono del timer-contatore 0

Se il timer-contatore 0 funziona in modo asincrono, è necessario tenere conto di alcune caratteristiche. Quando si passa tra sorgenti di clock timer-contatore asincrone e sincrone, il contenuto dei registri TCNT0, OCR0 e TCCR0 potrebbe danneggiarsi. Per evitare ciò, è necessario seguire la seguente sequenza di commutazione sicura:

1. Disabilitare gli interrupt del timer-contatore 0 cancellando i bit OCIE0 e TOIE0.

2. Selezionare la sorgente di clock richiesta utilizzando il bit AS0

3. Scrivi nuovi valori in TCNT0, OCR0 e TCCR0.

4. Quando si passa alla modalità di clock asincrono, attendere fino al ripristino dei flag TCN0UB, OCR0UB e TCR0UB.

5. Reimposta i flag di interruzione del contatore del timer 0

6. Abilitare gli interrupt se necessario

Il generatore è ottimizzato per l'utilizzo di un risuonatore al quarzo con frequenza di 32768 Hz. La frequenza di clock della CPU deve essere almeno quattro volte superiore alla frequenza del generatore. La scrittura su TCNT0, OCR0 o TCCR0 avviene su due fronti positivi di TOSC1, perché I dati vengono prima inseriti in un registro temporaneo e poi trasmessi a destinazione. Ciascuno dei tre registri menzionati ha i propri registri temporanei individuali. Ciò significa che, ad esempio, la scrittura su TCNT0 non influisce sul processo di scrittura sul registro OCR0. Per determinare in quale registro è stato scritto, viene implementato un registro di stato asincrono, ASSR.

Se viene selezionato il funzionamento asincrono, il generatore a 32768 Hz è costantemente attivo, ad eccezione della modalità di spegnimento e della modalità standby del MK.

Prescaler timer-contatore 0


La sorgente di clock TC0 è designata clkT0. Per impostazione predefinita, clkT0 è connesso a clkI/O. Se il bit AS0=1 nel registro ASSR, allora TC0 viene sincronizzato in modo asincrono dal pin TOSC1. In questo modo è possibile utilizzare TC0 come orologio in tempo reale (RTC). Se AS=1, i pin TOSC1 e TOSC2 non servono come porta C e tra loro può essere collegato un risuonatore al quarzo come sorgente di clock separata. Non è consigliabile collegare una sorgente di clock esterna al pin TOSC1.Il prescaler consente di selezionare i seguenti segnali di clock: clkT0S/8, clkT0S/32, clkT0S/64, clkT0S/128, clkT0S/256 e clkT0S/1024. È possibile interrompere la sincronizzazione. Se PSR0=1 nel registro SFIOR, reimposta il prescaler.

Per una descrizione dei registri 0 del timer-contatore a 8 bit, vedere le specifiche.

Lezione 13

Parte 1

PWM LED lampeggiante senza intoppi

Oggi esploreremo la possibilità di utilizzo modulazione dell'ampiezza dell'impulso in un microcontrollore AVR, o, come dice la gente, PWM.

Nella documentazione tecnica vedremo più spesso l'abbreviazione PWM O modulazione di larghezza di impulso, che è anche tradotto.

Cos'è comunque la modulazione dell'ampiezza dell'impulso?

PWM- questo è il controllo dell'illuminazione dei LED, della rotazione dei motori e di altri dispositivi in ​​un modo insolito, in cui questo controllo viene effettuato non dalla tensione applicata ai contatti, ma da impulsi quadrati. In questo caso, ci saranno solo due tipi di tensione: alta ( 1 ) e basso ( 0 ). Con questo metodo, la tensione risultante viene calcolata come media temporale tra il momento dello stato alto in un impulso e il tempo dello stato basso. Calcoliamo il rapporto tra il tempo (o latitudine) dello stato alto e il periodo totale dell'impulso. Lo chiamiamo ciclo di lavoro dell'impulso. Cioè, quanto più la tensione era alta durante il periodo, tanto maggiore era il ciclo di lavoro e, di conseguenza, maggiore era la tensione media risultante. Cioè, per trovare la tensione risultante, dobbiamo moltiplicare il ciclo di lavoro sufficientemente calcolato per la tensione e dividerlo per 100, poiché il ciclo di lavoro viene solitamente misurato in percentuale. Ad esempio, se in un impulso quadrato la larghezza dello zero logico è uguale alla larghezza dell'uno logico, il ciclo di lavoro sarà del 50% e se la tensione è di 5 volt, la tensione media risultante sarà pari a 2,5 volt. , eccetera. Possiamo vedere un quadro migliore della spiegazione di questa situazione guardando il video tutorial, il cui collegamento è riportato alla fine di questo articolo.

Questo è ovviamente un concetto molto semplificato di PWM. Esistono spiegazioni più serie per questa tecnologia, ma per i nostri esperimenti sarà abbastanza.

Cioè, per riassumere la spiegazione, controlliamo la tensione risultante, così come la luminosità del LED, la velocità angolare del motore elettrico e altri valori modificando il ciclo di lavoro degli impulsi.

Ma la cosa più interessante è: come è organizzato tutto questo nel nostro microcontrollore?

In un microcontrollore Modulazione dell'ampiezza dell'impulso AVR può essere organizzato come a livello di programmazione, COSÌ hardware.

Software organizzazione PWM- questo è quando ne attiviamo uno logico sulla gamba del controller per un certo tempo, quindi per un certo tempo - uno zero logico e così via in un ciclo. I vantaggi di questo metodo sono che possiamo organizzarci PWM su qualsiasi ramo di qualsiasi porta del controller, e lo svantaggio è che tutto ciò sarà associato a costi considerevoli in termini di tempo del processore e potrebbe anche essere associato ad alcuni errori che ne derivano.

Pertanto, in qualsiasi tecnologia cerchiamo sempre di aderire al metodo di implementazione dell'hardware.

Hardware organizzazione PWM nel MK AVR avviene a livello temporizzatore 2.

Come ricordiamo dalla lezione precedente, nel nostro particolare microcontrollore Atmega8 sono presenti tre timer. Entrambi i timer 0 e 2 sono a otto bit. Ma a livello del 2o timer, è organizzata la modulazione dell'ampiezza dell'impulso.

Diamo un'occhiata a questa immagine

Questo illustra quali bit dovremmo abilitare nel registro TCCR secondo timer per avviare la modulazione dell'ampiezza dell'impulso.

I bit WGM trasformano il timer in modalità PWM (PWM). Ci occuperemo delle parti rimanenti in seguito, se necessario.

E ora, per sentire tutto, abbiamo bisogno di un progetto, che creeremo ora.

Creiamo il progetto nello stesso modo delle lezioni precedenti. Chiamiamolo Test10, creiamo e aggiungiamo i file PWM.c e PWM.h, quest'ultimo prenderà forma automaticamente quando verrà creato il preprocessore con le apposite direttive. E nel file principale Test01.c scriveremo il codice standard

#includere"principale.h"

//—————————————-

vuoto porta_ini( vuoto)

PORTO=0x00;

DDRB=0x08;

//—————————————-

int principale( vuoto)

Port_ini();

Mentre(1)

Come vediamo nel codice, nella porta B abbiamo collegato il pin 3 all'uscita. Nella piedinatura del controller vediamo che questa gamba ha una designazione alternativa OC2, il che significa che questa gamba può funzionare direttamente con PWM

Possiamo anche collegare il file main.h dell'ultima lezione su LCD e correggere un po' il codice collegando lì il nostro nuovo modulo PWM

#ifndef PRINCIPALE_H_

#definire PRINCIPALE_H_

#definire F_CPU 8000000UL

#includere

#includere

#includere

#includere

#includere

#includere"PWM.h"

#finisci se /*MAIN_H_ */

Bene, ora iniziamo a scrivere il codice in una nuova libreria per lavorare direttamente con PWM, nel file PWM.c.

Lì includeremo anche il file header e creeremo un framework di funzioni per lavorare con PWM

#includere"PWM.h"

vuoto init_PWM_timer( vuoto)

{

}

E aggiungeremo un prototipo di questa funzione al file header della nostra libreria e collegheremo anche la libreria per lavorare con gli interrupt

#ifndef PWM_H_

#definire PWM_H_

#includere

vuoto init_PWM_timer( vuoto);

#finisci se /* PWM_H_ */

E chiama immediatamente questa funzione in main()

porta_ini();

init_PWM_timer();

Iniziamo ora a scrivere il codice direttamente nella funzione. Per prima cosa scriviamo tutti gli zeri nel registro ASSR, che esiste nel timer, ma non lo usiamo in alcun modo

vuoto init_PWM_timer( vuoto)

ASSR=0x00;

Passiamo quindi al registro di controllo del nostro timer. Abbiamo discusso lo scopo dei bit WGM e quali attiveremo. Ora i bit COM20 e COM21 sono responsabili della modalità PWM stessa. Selezioneremo questa modalità e di conseguenza attiveremo questi bit

E attiveremo una modalità in cui, all'inizio del conteggio, la tensione sulla gamba OC2 sarà in uno stato logico alto e non appena conteremo fino a un certo numero, la gamba andrà in uno stato basso e vi resterà fino alla fine del conteggio. E così via in cerchio.

E tutto quello che dobbiamo fare è impostare il divisore. Non abbiamo bisogno di una frequenza troppo alta. Ma quando era troppo piccolo, si notava anche lo sfarfallio, quindi attiviamo il valore successivo

Quindi attiveremo tutti e tre i bit.

Di conseguenza, il valore del registro sarà simile a questo

ASSR=0x00;

TCCR2=0b01101110; //PWM veloce, Cancella OC2 durante il confronto, clkT2S/256 (dal prescaler) (la frequenza reale sarà 8 MHz/256 = 31250 Hz)

Ora proviamo ad assemblare il progetto. Il progetto è andato bene. Nella parte successiva continueremo a lavorare con PWM.

Guarda il VIDEO TUTORIAL (clicca sull'immagine)

Visualizzazioni dei post: 9.484

Nei dispositivi a microcontrollore a volte è necessario generare un segnale analogico. A seconda della frequenza del segnale analogico, della risoluzione richiesta e del tipo di microcontrollore utilizzato, ciò può essere fatto in diversi modi. Vale a dire: utilizzando la modulazione di larghezza di impulso, utilizzando la funzionalità dei timer hardware o l'implementazione del software, utilizzando un convertitore digitale-analogico (DAC) integrato, utilizzando circuiti convertitori digitale-analogici esterni su elementi discreti o utilizzando dispositivi digitali esterni -microcircuiti convertitori analogici.

1. Il principio di generare un segnale analogico utilizzando PWM (PWM)

Un segnale PWM è un segnale digitale il cui periodo di ripetizione è costante ma la sua durata varia. Il rapporto tra la durata di un segnale PWM e il suo periodo è chiamato ciclo di lavoro. Facendo passare tale segnale attraverso un filtro passa basso, che equivale sostanzialmente all'integrazione, otteniamo un livello di tensione all'uscita del filtro proporzionale al ciclo di lavoro.


Pertanto, utilizzando questo coefficiente, è possibile generare segnali analogici di forma arbitraria. Inoltre, entrambi sono variabili, ad esempio un'onda sinusoidale, una sega o un linguaggio umano, e costanti (livello di tensione arbitrario).

1.1 Caratteristiche del segnale

Ampiezza massima dell'uscita analogica sarà determinato dall'ampiezza dell'unità logica del segnale PWM digitale. Se il microcontrollore è alimentato da +5 V, in parole povere l'ampiezza del segnale analogico in uscita sarà compresa tra 0 e 5 V.

Passo minimo di modifica del segnale analogico(risoluzione) sarà determinata dall’espressione:


dUa = Umax/2^n,


dove Umax è l'ampiezza massima del segnale analogico (V) e n è la profondità di bit del contatore che implementa PWM.

Ad esempio, un segnale PWM viene generato utilizzando un contatore software a 8 bit. Il numero di gradazioni del segnale PWM ottenibili utilizzando questo contatore è 2^8 = 256. Quindi la risoluzione del segnale analogico a Umax = 5 V sarà pari a


dUa = 5/256 = 0,0195 V.


Frequenza del segnale PWM verrà definito così:


Fpwm = Fcpu/(K*2^n),


dove Fcpu è la frequenza di clock del microcontrollore (Hz), K è il coefficiente di prescaler del contatore, n è la dimensione del bit del contatore.

Ad esempio, la frequenza di clock di un microcontrollore è 8 MHz, il coefficiente prescaler è 8 e la larghezza del contatore è 8 bit. Quindi la frequenza del segnale PWM in uscita sarà uguale a:

Fpwm = 8000000/(8*256) = ~3906 Hz


Frequenza di uscita analogica sarà determinato dall'espressione:

Fa = Fpwm/Ns = Fcpu/(K*2^n*Ns),


dove Fpwm è la frequenza del segnale PCB e Ns è il numero di campioni del segnale analogico.

Ad esempio, un segnale PWM è implementato su un contatore a 8 bit con un coefficiente prescaler di 8 e una frequenza di clock del microcontrollore di 8 MHz. La memoria del microcontrollore contiene 32 campioni di un segnale sinusoidale, che rappresentano un periodo. Quindi la frequenza della sinusoide di uscita sarà uguale a:

Fa = 8000000/(8*2^8 * 32) = ~122 Hz

La capacità di un DAC realizzato sulla base del PWM è equivalente alla capacità del contatore utilizzato.

1.2 Implementazione hardware del PWM

Tutti i microcontrollori moderni includono timer/contatori. Una o più modalità di questi timer sono progettate per generare un segnale PWM. Tipicamente, questo segnale viene generato su pin speciali. Ad esempio, il microcontrollore mega16 di Atmel ha un timer/contatore T0 a 8 bit che ha due modalità per generare un segnale PWM (PWM veloce e PWM con fase precisa) e il pin della porta B - OC0 (PINB3) viene utilizzato per emettere il segnale.

Il vantaggio di un'implementazione hardware di un segnale PWM è il basso carico del microcontrollore (l'interruzione viene chiamata una volta durante il periodo del segnale PWM), facilità d'uso e precisione (se ci sono poche interruzioni nel sistema). Gli svantaggi includono la risoluzione limitata dei contatori, la bassa frequenza, il numero limitato di canali su cui possono essere generati i segnali PWM. Sebbene esistano microcontrollori speciali appositamente "affilati" per generare un gran numero di segnali PWM.

1.3 Implementazione software del PWM

Puoi anche generare un segnale PWM a livello di codice. Per fare ciò è sufficiente creare un contatore software e, sulla base di un segnale timer hardware, incrementarne il valore e monitorare il raggiungimento dei valori estremi del contatore, ai quali il segnale PWM cambia stato.

Il vantaggio dell'implementazione del software è la semplicità, il numero illimitato di canali, la risoluzione illimitata. Naturalmente, condizionatamente illimitato, tenendo conto della memoria disponibile.Gli svantaggi dell'implementazione del software sono l'elevato carico del microcontrollore. Gli interrupt devono essere richiamati per ogni incremento del contatore e ogni volta bisogna verificare se ha raggiunto uno dei valori estremi. Inoltre, l'implementazione del software ha una precisione inferiore (maggiore jitter dei fronti del segnale) e una frequenza ancora più bassa (a causa del primo inconveniente).

Tuttavia, nonostante ciò, l'implementazione software del PWM è utile anche se è necessario generare un segnale analogico costante o alternato, ma a bassa frequenza.

Di seguito è riportato un esempio di codice che esegue la funzione di generare un segnale analogico utilizzando la modulazione di larghezza di impulso hardware e software. Il codice è scritto per il microcontrollore atmega16, frequenza di clock 8 MHz, compilatore IAR. Alle uscite PB2 e PB3 vengono generate due sinusoidi (di frequenze diverse) di 32 due campioni.


#includere
#includere
#includere

#definire SPWM_PIN 2

//tabella seno
__flash uint8_t tableSin =
{
152,176,198,218,234,245,253,255,
253,245,234,218,198,176,152,128,
103, 79, 57, 37, 21, 10, 2, 0,
2, 10, 21, 37, 57, 79,103,128
};

uint8_t softCount = 0;
uint8_t softComp = 0;

int principale(vuoto)
{
//impostazioni della porta
PORTAB = 0;
DDRB = 0xff;

//abilita l'interruzione per coincidenza T0
TIMSK = (1<//Modalità FastPWM, non inv. Segnale PWM, prescaler 8
TCCR0 = (1< (0<

//reimposta il registro di conteggio
TCNT0 = 0;
OCR0 = 0;

Abilita_interruzione();
mentre(1);
restituire 0;
}

//interrompe il timer T0
#pragma vettore = TIMER0_COMP_vect
__interrupt void Timer0CompVect(void)
{
statico uint8_t i = 0;
statico uint8_t j = 0;

OCR0 = tabellaSin[i];
io = (io+1) & 31;

//programma PWM
softConte++;
if (softCount == 0)(
PORTAB |= (1<softComp = tableSin[j];
j = (j + 1) & 31;
}

Se (softCount == softComp)(
PORTAB &= ~(1< }
}

1.4 Filtro per PWM

La frequenza di taglio del filtro deve essere compresa tra la frequenza massima dei segnali analogici generati e la frequenza del segnale PWM. Se la frequenza di taglio del filtro viene scelta vicino al limite della larghezza di banda del segnale analogico, il segnale verrà attenuato. E se la frequenza di taglio del filtro è vicina alla frequenza del segnale PWM, il segnale analogico semplicemente non “risalta”. Maggiore è la frequenza del segnale PWM, più facile sarà implementare il filtro di uscita.

Diamo un'occhiata a un esempio. Il segnale PWM è generato da un contatore hardware a 8 bit con un fattore di prescaler pari a 8, la frequenza di clock del microcontrollore è 8 MHz, il numero di campioni di segnale analogico è 32.

La frequenza del segnale PWM sarà pari a:

Fpwm = Fcpu/(K*2^n) = 8000000/(8*256) = ~3906 Hz

La frequenza del segnale analogico sarà pari a:

Fa = Fpwm/Ns = 3906/32 = 122 Hz

Scegliamo una frequenza di taglio di 200 Hz e calcoliamo le prestazioni del filtro RC passivo passa-basso. La frequenza di taglio di tale filtro è determinata dall'espressione:

Fc = 1/(2*Pi*R*C),

dove R è il valore del resistore (Ohm) e C è la capacità del condensatore (F).

Dopo aver specificato il valore di uno dei componenti, puoi calcolare il valore del secondo. Per un resistore con un valore nominale di 1 kOhm, la capacità del condensatore sarà pari a:


C = 1/(2*Pi*Fc*R) = 1/(6,28 * 1000*200) = ~0,8 µF


Selezioniamo il valore più vicino dalla serie E12: 0,82 µF. Con questi valori di filtro otterremo un segnale analogico simile.

Tuttavia, di norma, un elemento filtrante passivo non sarà sufficiente. Perché dopo di ciò il segnale analogico conterrà ancora un gran numero di armoniche.

Dopo aver fatto lampeggiare i LED, individuato le fonti di clock e di interruzione, era il momento di padroneggiare il timer del controller MSP430G2553.
Un timer è un meccanismo di conteggio legato agli impulsi provenienti da un segnale del generatore di orologio. Temporizzatore Temporizzatore_A è un temporizzatore a 16 bit. Ciò significa che conta da zero a binario 0b1111111111111111, o esadecimale 0xFFFF, o decimale 65535. Il timer è un dispositivo periferico e ha anche i propri interrupt.
Timer_A ha tre modalità operative.

Modalità di conteggio continuo, in cui il timer conta semplicemente da 0 a 0xFFFF, quindi ricomincia dall'inizio e così via all'infinito.

Modalità di conteggio diretto, in cui il timer funziona allo stesso modo, conta fino al limite superiore e ricomincia da 0. Solo in questa modalità è possibile scegliere il limite superiore fino al quale conterà il timer.

La modalità di conteggio inverso è simile alla modalità di conteggio in avanti in quanto è possibile selezionare il valore massimo del timer. La differenza è che, raggiunto il massimo, il timer inizia il conto alla rovescia, poi, raggiunto lo 0, ricomincia a contare, ecc.
Sui grafici è presente la designazione TACCR0: questo è il registro di acquisizione del confronto. Possono essercene due (TACCR0 e TACCR1), oppure tre (TACCR0, TACCR1 e TACCR2) a seconda del modello. In questo registro è possibile scrivere i cosiddetti punti chiave, al raggiungimento dei quali il timer attiverà un'interruzione.

I registri del timer A sono descritti in dettaglio di seguito:
TATTO– Registro di controllo timer_A, registro di controllo timer A. Utilizzato per collegare il timer ai segnali dell'orologio e selezionare le modalità operative.
NAPPAx,bit 8 e 9, indicano al timer quale orologio utilizzare.
IDx, i bit 6 e 7, indicano quale divisore di clock utilizzare, 2, 4 o 8. Viene divisa la frequenza ottenuta dopo aver applicato il divisore nel generatore di clock stesso.
MCx, bit 4 e 5, indicano la modalità operativa del timer. Se sono uguali a 0 (impostazione predefinita), il timer viene completamente fermato.
TACLR, bit 2. Se inserisci un 1, questo ripristinerà il timer. Il microcontrollore scrive automaticamente 0 su questo bit dopo il riavvio del timer.
TAIE e TAIFG, bit 0 e 1, rispettivamente. Controllano l'interruzione del timer, ne parleremo più avanti.
CATRAME– Registro Timer_A, Registro timer Un contatore, contiene il valore corrente del timer.
TACCRx– Registri di cattura/confronto timer_A, registri di cattura/confronto timer A. Possono essercene due (TACCR0 e TACCR1), possono essercene tre (TACCR0, TACCR1 e TACCR2) a seconda del modello di microcontrollore. Nella modalità confronto, inseriamo dei valori al loro interno, al raggiungimento dei quali il timer dovrebbe darci un segnale. TACCR0 viene spesso utilizzato per indicare il limite superiore del conteggio. In modalità di acquisizione, il processore scrive al loro interno il valore TAR corrente in base al segnale di ingresso.
TACCTLx– Registri di controllo di cattura/confronto Timer_A, registro di controllo del blocco di cattura/confronto Timer A. Le modalità operative dei registri di cattura/confronto dipendono dal suo valore.
CMx, bit 14 e 15, determinano il tipo di segnale utilizzato per l'acquisizione. (Sulla salita, sulla discesa, su entrambi i fronti. - Nota per.)
CCISx,Bit 12 e 13, selezionano da dove proviene il segnale di cattura.
SCS e SCCI, rispettivamente bit 11 e 10, sincronizzano il segnale di cattura con il segnale dell'orologio del timer. Tipicamente, il timer funziona in modo indipendente, in modo asincrono, da segnali esterni. (Io stesso non ho compreso appieno questa funzione, scriverò più in dettaglio nelle lezioni successive)
CAP, bit 8, selezione della modalità operativa, 1 – modalità di acquisizione, 0 – modalità di confronto.
OUTMODx, bit 5-7, selezione della modalità operativa del modulo di uscita, ovvero tipo di risposta a un evento di acquisizione o confronto.
CCIE e CCIFG, bit 4 e 0 rispettivamente, acquisiscono/confrontano l'elaborazione dell'interruzione.
CCI e FUORI, rispettivamente i bit 3 e 2, acquisiscono/confrontano input e output.
COV, bit 1, overflow di acquisizione. Impostato a 1 se è avvenuta una seconda acquisizione e la prima non è stata ancora letta. Deve essere ripristinato dal software.
TAIV– Registro vettoriale di interruzione Timer_A, registro vettoriale di interruzione Timer A. Poiché un'interruzione del timer può essere causata per diversi motivi, il contenuto di questo registro indica il motivo della chiamata dell'interruzione.
TAIVx I bit 1-3 contengono il tipo di interruzione che si è verificata, il che ci consente di intraprendere azioni diverse per gestire diverse cause di interruzione.

Quindi, se hai solo bisogno di far lampeggiare un LED o commutare un relè o simili a determinati intervalli, configurare un timer in questo caso è molto semplice.

TACCR0 = 62499; // periodo 62.500 cicli TACCTL0 = CCIE; // Consenti l'interruzione del timer quando viene raggiunto il valore CCR0. TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR; //Impostazione della modalità operativa Timer_A: // TASSEL_2 - sorgente clock SMCLK (SubMainCLocK), // configurato per impostazione predefinita per funzionare da DCO // ID_3 - divisore di frequenza per 8, da 1 MHz sarà 125kHz // MC_1 - modalità di conteggio diretto (fino a TACCR0) // TACLR - ripristino iniziale del timer

Ma complichiamo un po' il compito e facciamo in modo che il LED si accenda e si spenga dolcemente. Per fare questo dobbiamo usare PWM. Il principio del PWM è fornire tensione in impulsi con una frequenza fissa e un ciclo di lavoro variabile. Il PWM è caratterizzato da un parametro come il ciclo di lavoro: questo è il reciproco del ciclo di lavoro ed è uguale al rapporto tra la durata dell'impulso e il suo periodo.

Per maggiore chiarezza, la figura seguente mostra i segnali PWM per il duty cycle: a – 25%; b – 50%; c – 75%; g – 100%.

t0 – tempo di impulso;
T – periodo;
Modificando t0 è possibile ottenere diversi valori di tensione media ai capi del carico, modificando così la luminosità del LED.
Il periodo di modulazione dell'ampiezza dell'impulso deve essere costante e maggiore della durata dell'impulso. Pertanto, scriviamo TACCR0 = 600; // periodo 600 cicli. Ho selezionato questo numero sperimentalmente in modo che il funzionamento del timer potesse essere visto ad occhio nudo.
Poiché il LED dovrebbe accendersi lentamente, la durata dell'impulso iniziale dovrebbe essere molto breve, ad es. TACCR1 = 10; // tempo di impulso 10 cicli. TACCR1 è il secondo registro di cattura/confronto del timer A. Quindi, risulta che quando viene raggiunto il valore TACCR0 = 600, il timer genererà un interrupt in cui imposteremo l'uscita del microcontrollore su uno, che sarà l'inizio di l'impulso. In questo caso, il timer viene azzerato e ricomincia a contare da zero fino a raggiungere TACCR1 = 10, quindi verrà generato un interrupt nel secondo registro di cattura/confronto, in cui imposteremo a zero l'uscita del microcontrollore. Pertanto, la durata dell'impulso t0 durerà 5 cicli di clock.
Affinché il LED possa aumentare l'intensità della luce, è necessario aumentare il tempo di impulso. Per fare ciò, dopo ogni interruzione da TACCR0 aggiungeremo un valore al valore corrente di TACCR1. In questo caso, il valore massimo che TACCR1 può avere sarà uguale al periodo, ovvero 600. A seconda del valore che aggiungiamo, dipenderà la fluidità e la velocità di variazione dell'intensità del bagliore.

TACCR0 = 600; // Periodo TACCR1 = 5; //Tempo dell'impulso TACCTL0 = CCIE; // Consenti l'interruzione del timer quando viene raggiunto CCR0. TACCTL1 = CCIE; // Consenti l'interruzione del timer quando viene raggiunto CCR1. TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR; //Impostazione della modalità operativa Timer_A

Ora è necessario scrivere un gestore di interruzione per TACCR0, che imposterà l'inizio di ogni nuovo periodo, nonché aggiungerà o sottrarrà il valore di TACCR1 in modo che il LED si accenda e si spenga altrettanto dolcemente.

#pragma vettore = TIMER0_A0_VECTOR __interrupt void CCR0_ISR(void) //vettore di interruzione per TACCR0, timer A ( P1OUT |= BIT0; // imposta il bit zero su uno se (TACCR1><=5) // если TACCR1 меньше минимального значения, то увеличиваем TACCR1 { indeX=2; } if (indeX == 1) { --TACCR1; // уменьшаем TACCR1 на 1 } if ((indeX == 2) || (indeX == 0)) { ++TACCR1; // увеличиваем TACCR1 на 1 } }

L'interruzione per TACCR1 sarà simile a questa.

#pragma vector=TIMER0_A1_VECTOR __interrupt void CCR1_ISR(void) //vettore di interrupt per TACCR1, timer A ( P1OUT &= ~BIT0; // imposta il bit zero della porta P1 su zero. TAIV &= ~TA0IV_TACCR1; // reimposta l'interrupt bandiera. )

Tieni presente che nel primo caso, nel gestore degli interrupt di TACCR0, non ho reimpostato il flag di interrupt, ma per TACCR1 l'ho fatto. Questo perché il flag di interruzione per TACCR0 viene reimpostato automaticamente quando viene richiamato un tale interrupt, ma per TACCR1 deve essere reimpostato manualmente.

Ora puoi comporre il testo completo del programma.

#includere /* Variabili globali */ unsigned int indiceX = 0; /* Dichiarazione della funzione */ void main(void) ( WDTCTL = WDTPW + WDThold; // disabilita il watchdog timer P1DIR |= 0x01; // imposta il bit zero della porta P1 sull'uscita P1OUT = 0x01; // imposta lo zero bit della porta P1 su uno BCSCTL1 = CALBC1_1MHZ; // Imposta la frequenza DCO DCOCTL = CALDCO_1MHZ; TACCR0 = 600; // Periodo TACCR1 = 10; // Tempo di impulso TACCTL0 = CCIE; // Consenti l'interruzione del timer quando CCR0 è raggiunto TACCTL1 = CCIE; // Consentire l'interruzione del timer raggiungendo CCR1 TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR; //Impostazione della modalità operativa Timer_A: // TASSEL_2 - sorgente orologio SMCLK (SubMainCLocK), // configurato per impostazione predefinita per operare da DCO // ID_3 - divisore di frequenza per 8, da 1 MHz sarà 125kHz // MC_1 - modalità di conteggio diretto (fino a TACCR0) // TACLR - reset iniziale del timer _enable_interrupt(); // abilita tutti gli interrupt) #pragma vector = TIMER0_A0_VECTOR __interrupt void CCR0_ISR(void) //vettore di interrupt per TACCR0 , Timer A ( P1OUT |= BIT0; // imposta il bit zero a uno if (TACCR1>=(TACCR0-5)) // se TACCR1 è maggiore di TACCR0, quindi diminuire TACCR1 ( indice=1; ) se (TACCR1<=5) // если TACCR1 меньше минимального значения, то увеличиваем TACCR1 { indeX=2; } if (indeX == 1) { --TACCR1; // уменьшаем TACCR1 на 1 } if ((indeX == 2) || (indeX == 0)) { ++TACCR1; // увеличиваем TACCR1 на 1 } } #pragma vector=TIMER0_A1_VECTOR __interrupt void CCR1_ISR(void) //вектор прерывания для TACCR1, Таймера А { P1OUT &= ~BIT0; // устанавливаем нулевой бит порта Р1 в ноль. TAIV &= ~TA0IV_TACCR1; //сбрасываем флаг прерывания. }

Quindi, facciamo lampeggiare il controller, lanciamo il programma e vediamo che il LED rosso si accende lentamente e si spegne, si accende e si spegne.
Questo programma è molto comodo da usare nella pratica. Diciamo che devi modificare la luminosità di una lampada a diodi o la velocità di rotazione di un motore DC, tutte queste cose possono essere perfettamente implementate utilizzando PWM, che può essere controllato utilizzando un timer disponibile nel controller MSP430G2553. Sul nostro sito Web apparirà sicuramente una serie di articoli sul controllo di un motore CC tramite PWM, dove applicheremo queste competenze nella pratica.