In this tutorial we will set up the TIMER0 in fast pwm mode and use it to generate
PWM signals of varying duty cycles. In this way we would be generating analog
signals of voltages between 0 and 5v. In the example we will connect this output
to a LED and see how it varies its brightness. Please see the previous tutorials
on PWM and TIMERs before reading this tutorial.

PWM

Timers

Setting Up TIMER0 in Fast PWM mode

Setting up the TIMER0 in fast pwm mode is very easy and just require one line
of code. You only need to deal with one register named TCCR0 (Timer
Counter Control
Register For Timer 0).
You just need to set up various bits in it to get the required setting. The
various bits of TCCR0 is given below.

TCCR0

This register is used for configuring the TIMER0. See Timer Tutorial for more
info. The explanation of various bits of this register is as follows.

Bit No
7
6
5
4
3
2
1
0
Name
FOC0
WGM00
COM01
COM00
WGM01
CS02
CS01
CS00
Initial Val
0
0
1
0
0
0
0
0

(Note The Bits in RED are discussed here)

WGM – Wave Form Generation Mode

The table below shows the various modes supported by TIMER0. We have covered
Normal mode in "Timer0
tutorial
" and CTC mode in "Timers
In compare mode
" tutorial. And this tutorial we are interested in Fast
PWM mode.

Mode
WGM00
WGM01
Mode Of Operation
0
0
0
Normal
1
0
1
PWM Phase Correct
2
1
0
CTC
3
1
1
Fast PWM

From the table it is clear that for Fast PWM we need mode 3. To get it we must
set WGM00=1 and WGM01=1

COM – Compare Output Mode

These bits are used to set the Output mode in various Wave form generation
mode. For Fast PWM mode these can be used to achieve following output modes.

COM01
COM00
Output Mode
0
0
Normal Port Operation (OC0 disconnected)
1
0
RESERVED
0
1
Non Inverted PWM
1
1
Inverted PWM

We need the "Non Inverted PWM output mode" so we set COM01=0 and
COM00=1

CS – Clock Select

These are used to set an Input Clock for TIMER. We set them as follows to get
Ftimer=F_CPU (i.e. no prescalling). See "Timer
Tutorial
" for more info.

CS02 = 0

CS01 = 0

CS00 = 1

Now the TIMER is in Fast PWM mode to vary its output duty cycle we just need
to set the OCR0 (Output Compare Register for Timer 0). For example setting it
to 0 will generate PWM with duty cycle 0% (Totally off) while setting it to
128 will generate 50% duty cycle and 255 will generate 100% duty cycle signals.

Note: The output waveform is available in the associated Output Compare Pin
of the microcontroller. For example for Timer 0 the associated OC pin is OC0.
You can find its location from Pin diagram in datasheet. In ATmega16 and ATmega32
it is on PORTB bit 3, i.e. PB3. This pin must be set to output to
get the PWM signals.

Sample Program

The in the following program we set up TIMER0 in fast pwm mode and use the
generated PWM signals to vary the brightness of a LED. This is the simplest
program to get you started with PWM signal generation. We start with minimum
brightness and increase it gradually and then again reduce it gradually to zero.
This process is repeated as long as the system is powered.


#include <avr/io.h>
#include <util/delay.h>

void InitPWM()
{
   /*
   TCCR0 - Timer Counter Control Register (TIMER0)
   -----------------------------------------------
   BITS DESCRIPTION
   

   NO:   NAME   DESCRIPTION
   --------------------------
   BIT 7 : FOC0   Force Output Compare [Not used in this example]
   BIT 6 : WGM00  Wave form generartion mode [SET to 1]
   BIT 5 : COM01  Compare Output Mode        [SET to 1]
   BIT 4 : COM00  Compare Output Mode        [SET to 0]

   BIT 3 : WGM01  Wave form generation mode [SET to 1]
   BIT 2 : CS02   Clock Select               [SET to 0]
   BIT 1 : CS01   Clock Select               [SET to 0]
   BIT 0 : CS00   Clock Select               [SET to 1]

   The above settings are for
   --------------------------

   Timer Clock = CPU Clock (No Prescalling)
   Mode        = Fast PWM
   PWM Output  = Non Inverted

   */


   TCCR0|=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);

   //Set OC0 PIN as output. It is  PB3 on ATmega16 ATmega32

   DDRB|=(1<<PB3);
}

/******************************************************************
Sets the duty cycle of output. 

Arguments
---------
duty: Between 0 - 255

0= 0%

255= 100%

The Function sets the duty cycle of pwm output generated on OC0 PIN
The average voltage on this output pin will be

         duty
 Vout=  ------ x 5v
         255 

This can be used to control the brightness of LED or Speed of Motor.
*********************************************************************/

void SetPWMOutput(uint8_t duty)
{
   OCR0=duty;
}

/******************************************************************** 

Simple Wait Loop

*********************************************************************/

void Wait()
{
 _delay_loop_2(3200);
}

void main()
{
   uint8_t brightness=0;

   //Initialize PWM Channel 0
   InitPWM();

   //Do this forever

   while(1)
   {
      //Now Loop with increasing brightness

      for(brightness=0;brightness<255;brightness++)
      {
         //Now Set The Brighness using PWM

         SetPWMOutput(brightness);

         //Now Wait For Some Time
         Wait();
      }

      //Now Loop with decreasing brightness

      for(brightness=255;brightness>0;brightness--)
      {
         //Now Set The Brighness using PWM

         SetPWMOutput(brightness);

         //Now Wait For Some Time
         Wait();
      }
   }
}

Download
Sample Program

Download
Compiled HEX file for ATmega16 / ATmega32 @ 1 MHz

Hardware Setup

To run and test this program you need an AVR MCU (ATmega16 or ATmega32)(ATmega8
won’t work!). To keep the hardware simple we will use the MCU with internal
1MHz oscillator (this is default factory setting for new MCUs). We will add
a good quality RED LED to output compare pin (OC0) of the MCU. This is PIN no
4 on ATmega16/32 Micros. Vcc PIN (pin 10) is connected to +5v and Gnd PIN(pin
11,31) is connected to gnd. This is not show in diagram.

avr pwm controlled led schematic project

Fig. 1 – A PWM controlled LED

 

 

You can program the chip using this simple
avr programmer
or buy
a USB Programmer
.

Video

The PWM controlled LED in Action !!!