PWM in Atmega 16- Part 2
In the part one of this article, I have written about the introduction of PWM. In this article, you will learn in-depth knowledge of PWM and how to use PWM in atmega16.
Generating PWM using Timer in CTC mode
Well, you can generate the PWM signals by using “timer in CTC mode”. We can implement that by activating the interrupt of compare match and overflow in the timer control register. Here, I am not telling how to do that because I have already explained this here- Timer in CTC mode. Below is the program of generating PWM using timers.
#include <avr/io.h>
#include <avr/interrupt.h>
void timerinctcinit(int duty)
{
TCCR0=(1<<WGM01)|(1<<CS01)|(1<<CS00);
TCNT0=0;
TIMSK=(1<<OCR0)|(1<<TOIE0);
OCR0=duty;//between 0 to 255 127 is almost half
sei();
}
int main(void)
{
DDRA=0xff;
timerinctcinit(127);
PORTA=0xff;
while (1)
{
//nothing required here as all the working is done in interrupt
}
}
ISR(TIMER0_COMP_vect)
{
PORTA = 0x00;
}
ISR(TIMER0_OVF_vect)
{
PORTA=0xff;
}
Although the above program works fine, Atmega 16 has inbuilt PWM modes, let us learn how to use that.
Using PWM modes in Atmega 16
Now, the above program is good and works fine. But AVR controllers have all of these controls built-in. The only problem with that is it is pin constraint. So, if you are looking for much accuracy, and okay with pin constraint, you should follow the article.
PWM Modes
There are several modes of PWM in Atmega 16, these are
Fast PWM
This is the most useful and simplest of all the modes. In this mode, the timer counts from 0 to 255 and the output signal is high at the starting of the timer. When the match occurs between OCRx Register, the output signal becomes low. This gives us the control over duty cycle as we can vary the value of OCRx register.
Phase-correct PWM
In this mode, the timer starts from 0 and counts all the way up. The output signal Is high when the timer starts. When the compare occurs, the signal becomes low. Till now, it is the same as Fast PWM but when the catch starts now. The counter tarts decreasing the value when it reaches the top value and when the compare occurs backward, the signal becomes high. This gives us control over the phase of the output signal.
Now, both of these modes also has an additional mode that gives the control over output frequency. While we are at it, let us understand those two as well
Varying the timer top limit: fast PWM
In this mode, the timer starts from 0 and rather than going to 255, it goes up to the OCR. The gives us the more control of the frequency of the signal. You can toggle the signal each time the signal reaches the OCR value.
Varying the timer top limit: phase-correct PWM
Same as Varying the timer top limit, the timer I phase correct PWM can be configured to reset. Now you might be wondering the difference between these two?
Suppose the timer is set to fast PWM mode and is set to count up to an OCRnA value of 3. The timer will take on the values 012301230123… Note that there are 4 clock cycles in each timer cycle. Thus, the frequency will be divided by 4, not 3. The duty cycle will be a multiple of 25% since the output can be high for 0, 1, 2, 3, or 4 cycles out of the four. Likewise, if the timer counts up to 255, there will be 256 clock cycles in each timer cycle, and the duty cycle will be a multiple of 1/256. To summarize, fast PWM divides by N+1 where N is the maximum timer value (either OCRnA or 255).
Now consider phase-correct PWM mode with the timer counting up to an OCRnA value of 3. The timer values will be 012321012321… There are 6 clock cycles in each timer cycle (012321). Thus the frequency will be divided by 6. The duty cycle will be a multiple of 33% since the output can be high for 0, 2, 4, or 6 of the 6 cycles. Likewise, if the timer counts up to 255 and back down, there will be 510 clock cycles in each timer cycle, and the duty cycle will be a multiple of 1/255. To summarize, phase-correct PWM divides by 2N, where N is the maximum timer value.
Source- https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
Now that we know the modes, I think we know everything we need except about the configuration of the register.
Selecting the Modes of PWM
It depends on your project and how much control you need. If you just need the simpler control over duty cycle, fast PWM is better. But if you need more control over duty cycle and frequency of the output wave, select phase correct PWM.
The Program
In this program, I am using timer 0 of Atmega 16, which is an 8-bit register. The register we are looking for is TCCR0. Let’s look into its bits
TCCR0 Register
BIT-6:3-WGM Bits
The value we can give to these bits are given below in the table.
Bit 5:4 -Compare Output Modes
These bits are used to program the behavior of the controller when compare match occurs. You can set any one of these values according to your need. The pin it controls is PB3 of Atmega 16. Also, this is given for fast PWM. For more details about these bit- please see page 84 of the Atmega 16 datasheet. You can download the datasheet by clicking here.
Now there are prescaling bits left, I am assuming that you know about these bits here. If you don’t know about prescaling and it’ bits, I highly recommend you to visit this post first.
We have everything we need- let’s write a program it.
#include <avr/io.h>
#include <util/delay.h>
void InitPWM()
{
TCCR0|=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00); //Fast PWM, non-inverting mode and no prescaler.
DDRB|=(1<<PB3); //setting the output pin of 4th pin of Port B-PB3.
//0 to 255 - 0 means 0% and 255 means 100% duty cycle
}
void setduty(char duty)
{
OCR0=duty;
}
void main()
{
InitPWM();
setduty(127); //setting the duty cycle to 50%
while(1)
{
//everything is already set in hardware, don't need to do anything
}
}
I hope this article helps you guys to understand about PWM in Atmega16. We will do some projects based on PWMs later on. Well, see you next time.
Shouldn’t it be ocie0 instead of ocr0 in TIMSK reg in ctc working as pwm example?
yes..!! It should be the OCR0 in TIMSK reg. Thanks for reading and correcting the blog. I will update it..!!