Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PWM in Atmega328 using Code Vision AVR

Status
Not open for further replies.

djc

Advanced Member level 1
Advanced Member level 1
Joined
Jan 27, 2013
Messages
402
Helped
3
Reputation
6
Reaction score
2
Trophy points
1,298
Location
India
Activity points
4,554
Hello,

I have to use all the 6 PWM pins in Atmega328 using codevision AVR. However i am stuck with configuring in Timer0 PWM itself. Below is the simple code with nothing in main and timer0 overflow interrupt and compare match A and B interrupt. Here pins OCR0A and OCR0B are toggling with same frequency though i am changing OCR0A and OCR0B values in Timer0 overflow interrupt. Can anybody tell me why is this happening.

Code:
#include <mega328p.h>

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
OCR0A=250;                         ///////////////////////Change in OCR0A value
OCR0B = 100;                       ///////////////////////Change in OCR0B value
PORTD.6 = 1;
PORTD.5 = 1;    
}

// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{

PORTD.6 = 0;
}

// Timer 0 output compare B interrupt service routine
interrupt [TIM0_COMPB] void timer0_compb_isr(void)
{

PORTD.5 = 0;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=Out Func5=Out Func4=In Func3=In Func2=In Func1=Out Func0=Out 
// State7=T State6=0 State5=0 State4=T State3=T State2=T State1=0 State0=0 
PORTD=0x00;
DDRD=0x63;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000.000 kHz
// Mode: Normal top=FFh
// OC0A output: Toggle on compare match
// OC0B output: Toggle on compare match
TCCR0A=0x50;
TCCR0B=0x01;
TCNT0=0x00;
OCR0A=0x0A;
OCR0B=0x0A;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x07;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

      };
}
I checked toggling frequency using scope.

Thanx
 

Hi,

It depends on configuration...and I didn't go through your setup....
But with OCRx registers for PWM you don't change frequency, you change duty cycle.

To do this you don't use the "toggle pin" but you use one of the true PWM setup.
Use CTC mode.
You don't need interrupts, you don't need ISRs, all PWM can be done by hardware without processing power (just setup).

There are more than enough examples and discussions about PWM, first go through them, then refer to one if the examples.

Klaus
 

Thank you Klausst,
It means we don't need even Timer0 interrupt to modify the values of OCRx registers.
 

Hi,

You may use the interrupt, but there´s no need for it.

Read the datasheet: I´m about sure you may wirte to the OCRx registers at any time, but internally its updated when the conter restarts.

Klaus
 

Thanx Klausst,
I used timer0 interrupt and used OCR registers for PWM. now when timer0 interrupt occurs, OCR registers get their values for pulse width. It's working now.
 

Hi,

may I ask where you see the benefit in using interrupts?

out of curiosity I checked the datasheet. It says:
The OCR0x Registers are double buffered when using any of the Pulse Width Modulation (PWM) modes. For
the normal and Clear Timer on Compare (CTC) modes of operation, the double buffering is disabled. The
double buffering synchronizes the update of the OCR0x Compare Registers to either top or bottom of the
counting sequence. The synchronization prevents the occurrence of odd-length, non-symmetrical PWM pulses,
thereby making the output glitch-free.
The OCR0x Register access may seem complex, but this is not case. When the double buffering is enabled, the
CPU has access to the OCR0x Buffer Register, and if double buffering is disabled the CPU will access the
OCR0x directly.

Klaus
 

Hello,
I have to generate sine waves for inverter. So using timer interrupts.

Thanx
 

Hi,

I have to generate sine waves for inverter. So using timer interrupts.
Makes sense.
You didn´t mention SPWM before, thus I was confused...

Still you could do it without interrupt....But polling flags in main loop isn't an elegant solution. I also prefer the interrupt solution for SPWM.

Klaus
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top