Wednesday, January 04, 2012

avr17

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).
  1. Fast PWM
  2. 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
avr timer pwm generation tutorial

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).
avr pwm generation tutoraia

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 of ATmega32.

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.
pwm generation process with avr timer

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.