Phase And Frequency Correct PWM

This tutorial explains the work of PWM in phase & frequency correct mode

For this example we are using Attiny2313 microcontroller

**Attiny2313 running @ 8 MHz with Prescale of 8

**Time for one instruction = 1 ÷ (crystal frequency ÷ Prescale) => 1 ÷ (8 ÷ 8) = 1 uS

**************************************************************************************************

In this mode of operation during the time (A0 + A1) the O/P PORTPB3 is in LOW state & during the time (B0 + B1) the O/P PORTB3 is in HIGH state.

In our program if we use OCR1A = 30,000 & ICR1 = 60,000 and on observing the O/P on DSO you will see the ON time of the pulse as (B0 + B1) = 60 mS & the OFF time of the pulse as (A0 + A1) = 60 mS. Now we see that in practical how we get this ON & OFF value, when we switch ON the supply TIMER1 start from 0, while up counting when TIMER1 value matches with OCR1A value then a change in state of PORTB3 occurs let say from OFF to ON this ON will continue up to TIMER1 matches with ICR1 + while down counting when TIMER1 matches OCR1A, again a change in state of PORTB3 occurs from ON to OFF, this OFF continues up to TIMER1 reaches bottom while down counting + TIMER1 matches OCR1A while up counting and this cycle continues. In brief from the Fig.1 we can say that OFF time of the pulse is A0 + A1 & the ON time of the pulse is B0 + B1 from the above details ** if the controller is running @ 8 MHz then time for one instruction with prescale as 8 = 1÷(8÷8) uS = 1 uS.

 

Time taken by TIMER1 to reach up to OCR1A = 30,000 counts * 1 uS = 30,000 uS = 30 mS Now from the Fig.1 A1 = 30 mS & A0 = 30 mS this means the OFF time of the pulse = A1 + A0 = 30 + 30 = 60 mS.

Time taken by TIMER1 to reach up to ICR1 from OCR1A = ICR1 - OCR1A = 60,000 - 30,000 = 30,000 uS = 30 mS.

Now from the Fig.1 B0 = 30 mS & B1 = 30 mS this means the ON time of the pulse = B0 + B1 = 30 + 30 = 60 mS.

You can verify the above theoritical resulys with pratcial results by running the below mentioned program in AVR microcontroller & observing the O/P waveform at PORTB3 as shown in Fig.2, Fig.3 & Fig.4

Phase & Frequency Corrected PWM code :

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

uint16_t i;

 int main(void)

{

   DDRB |= (1 << 3);

   // Config PORTB3 as output port

   ICR1 = 60000;

   // Put 60,000 in ICR1

   OCR1A = 30000;

   // Put 30,000 in ICR1

   TCCR1B |= (1 << WGM13);

   TCCR1A |= (1 << COM1A1) | (1 << COM1A0);

   TCCR1B |= (1 << CS11);

   while(1)

         {                                       

         }

Download Code

You can also update or change the value of OCR1A while the program is running to get varying PWM duty cycle, use below mentioned code

 

Phase & Frequency Corrected PWM code with continuous varying duty cycle :

 

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

uint16_t i;

int main(void)

{

   DDRB |= (1 << 3);

   DDRD |= (1 << 6);

   ICR1 = 1000;

   OCR1A = 0;

   TCNT1 = 0;

   TCCR1B |= (1 << WGM13);

   TCCR1A |= (1 << COM1A1) | (1 << COM1A0);

   TCCR1B |= (1 << CS11);

   while(1)

               {         

                         for(i=0;i<=1000;i++)

                                {

                                   OCR1A = i;

                                  _delay_ms(5);

                                 }                                     

                 }

}

Download Code