In the last
tutorial you saw how the PWM technique helps us generate analog signals
from a microcontroller. In this tutorial we will see how PWM generation is implemented
Before you begin please see
Generation of PWM signals is such a common need that all modern microcontrollers
like AVR has dedicated hardware for that. The dedicated hardware eliminates
the load of generation of PWM signal from software (thus frees the CPU ). Its
like asking the hardware to generate a PWM signal of a specific duty cycle and
the task of CPU is over. The PWM hardware with start delivering the required
signal from one of its PINs while the CPU can continue with other tasks.
In AVR microcontrolers PWM signals are generated by the TIMER units. (See AVR
Timer Tutorials) . In this tutorial I will give you the basic idea of how PWM
signals are generated by AVR timers. Their are two methods by which you can
generate PWM from AVR TIMER0 (for ATmega16 and ATmega32 MCUs).
- Fast PWM
- Phase Correct PWM
Don’t worry from their names they will become clear to you as we go on. First
we will be considering the Fast PWM mode.
PWM Generation Fundas
We will use the simplest timer, TIMER0 for PWM generation.(Note TIMER0 of ATmega8
cannot be used for PWM generation, these are valid for ATmega16 and ATmega32).
In this part we won’t be dealing with any code, we would just analyze the concepts.
So lets start!
We have a 8bit counter counting from 0-255 and the goes to 0 and so on. This
can be shown on graph as
Fig. 1 – AVR Timer Count Sequence for Fast PWM.
The period depends upon the prescalar
settings. Now for PWM generation from this count sequence we have a new "friend"
named OCR0 (Output Compare Register Zero , zero because its for TIMER0 and there
are more of these for TIMER1 & TIMER2). We can store any value between 0-255
in OCR0, say we store 64 in OCR0 then it would appear in the graph as follows
(the RED line).
Fig. 2 – AVR Timer Count Sequence for Fast PWM with OCR0=64
So how does this Output Compare Register generates PWM? Well, the answer follows.
When the TIMER0 is configured for fast PWM mode,while up counting whenever
the value of TIMER0 counter (TCNT0
register) matches OCR0 register an output PIN is pulled low (0) and when counting
sequence begin again from 0 it is SET again (pulled high=VCC). This is shown
in the figure 3. This PIN is named OC0 and you can find it in the PIN configuration
Fig. 3- AVR Timer Count Sequence for Fast PWM with OCR0=64
From the figure you can see that a wave of duty cycle of 64/256 = 25% is produced
by setting OCR0=64. You can set OCR0 to any value and get a PWM of duty cycle
of (OCR0 / 256). When you set it to 0 you get 0% dutycycle while setting it
to 255 you get 100% duty cycle output. Thus by varying duty cycle you can get
an analog voltage output from the OC0 PIN. The resolution of this PWM is 8BIT.
Watch the animation below for a step by step explanation of PWM generation process.
Fig. 4 – PWM Generation Process from AVR Timers.
One note about OCR0 is that it is double buffered. But what does than means?
It is just for your help. Double buffering means that you cannot directly write
to OCR0 when ever you write to OCR0 you are actually writing to a buffer. The
value of buffer is copied to actual OCR0 only during start of cycle (when TCNT0
wraps from 255 to 0). This nice feature prevents update of OCR0 in between the
cycles. The new value of OCR0 comes into effect only on beginning of a new cycle
even if you write to it in between a cycle.
In next tutorial we will see how to setup the TIMER0 in fast PWM mode, actually
generate some PWM signals and use this to control the brightness of a LED.
To be continued …