Noob PWM

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to dim an LED using PWM. I have Atmega16 on STK500. Here is the code.

#include 
#include 

int main(void)
{
	
	DDRB |= ((1<<0)); // set led 1 as output
	
	TCCR1B |= ((1<<WGM13) | (1<<WGM11));	//Set up timer in PWM Phase Correct mode

	ICR1 = 250; //set top value

	OCR1A   = 125;// Set CTC compare value 

	TIMSK |= (1 << OCIE1A); // Enable CTC interrupt

	TCCR1B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64 

	sei(); //  Enable global interrupts 

	for(;;) // loop
	{

	}

}


ISR(TIMER1_COMPA_vect)
{
   PORTB ^= (1<<0); // toggle led
}

I did not understand half the stuff in the data sheet. How I believe PWM works is the timer counts from 0 to ICR1 value and then back to 0. When it reaches OCR1A value the interrupt occurs and led is toggled. Is that right ? Can I dim an LED with out the interrupt but pure hardware?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, the interrupt is not required. The AVR's pwm hardware will take care of the OCR1A port pin if so configured.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to set the COMxx bits (which are usually in TCCR1A) to get automatic toggling of a pin (no interrupts required). However, this is restricted to a specific pin.

If you want to use another pin, you need to use interrupts. But for this the compare interrupt is not enough. You would also need the overflow interrupt. In one of the interrupts you would send the pin high, the other send it low.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Setting (1<<WGM13), (1<<WGM11), (1<<WGM10) for Phase Correct PWM (16 bit Timer 1) says that the top value is OCR1A. This confuses me, isn't OCR1A used to set the compare value ? IF OCR1A is used as the top value how would u toggle a pin ? Also I think I figured out how to dim the LED without the interrupt.
Does this code give me a 10% duty cycle ?

int main(void)
{
	
	DDRD |= 0xFF; // set all LEDs as output 
	
	TCCR1A |= ((1<<WGM13) | (1<<WGM11));	//Set up timer in  PWM Phase Correct mode top value ICR1

	ICR1 = 500;  // set top value

	OCR1A = 450; //set compare value
	
	TCCR1A |= (1 << COM1A1); //clear OC1A/OC1B up count , set downcount

	TCCR1B |= (1 << CS11); // Start timer at Fcpu/64 

	for(;;) // loop
	{

	}

}

Thanks in advance

Edit

I was wondering if I can damage my STK500 by connecting atmega16 pins to a circuit on a separate board through the expand port. If I mess up a circuit will the STK get damaged or only the atmega ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With the modes that use OCR1A as TOP you can only use OCR1B as the duty cycle. With the modes that use ICR1 or a fixed value you can use both OCR1A and OCR1B as separate duty cycles.

Quote:
Does this code give me a 10% duty cycle ?

That code would give you a 90% duty cycle (output is high from 0 to 450 and from 450 to 0).
Quote:
I was wondering if I can damage my STK500 by connecting atmega16 pins to a circuit on a separate board through the expand port. If I mess up a circuit will the STK get damaged or only the atmega ?

That really depends on how you mess it up.

Regards,
Steve A.

The Board helps those that help themselves.