NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » Fast PWM output on PB1

October 16, 2011
by mmgn
mmgn's Avatar

Does anyone know why the following code doesn't result in a slowly blinking LED on PB1?

#define F_CPU 14745600
#include <stdio.h>
#include <math.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
int main() {
  OCR1A = 14400; // 1 sec period with clock/1024
  OCR1B = 7200; // 50% duty cycle
  // set PB1 to output; this pin is OC1A
  DDRB |= (1<<PB1);
  // WGM[13:10]=1111 is fast PWM 
  // COM1A[1:0]=10 non-inverting output on OC1A 
  // CS[12:10]=101 for clock/1024
  TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1); 
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS12) | (1<<CS10);

  while(1) {
    // nothing
  } 
  return 0;
}

The above code works as expected if I connect an LED to PB2 and make the following modifications:

DDRB |= (1<<PB2);
TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1B1);

Am I misunderstanding the datasheet? Looking at p.131, Table 15-2, setting COM1A[1:0]=10 should result in a non-inverting output on OC1A (which is the pin labeled PB1).

October 17, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi mmgn,

You are running into a problem here because you are using the mode that uses OCR1A as the TOP register. This does not allow you to use OC1A as an output pin because normally OCR1A is what that output uses to do its comarison agains (to set the duty cycle). Bascially in this mode you are gaining the ability to explicitly set the TOP value of your counter, but giving up a usable output for your PWM. You could turn off WGM10 and then use ICR1 as the register to hold the TOP value, then you should be able to use both OC1A and OC1B as PWM outputs. Does that make sense?

Humberto

October 17, 2011
by mmgn
mmgn's Avatar

Thank you very much, Humberto!! Your post helped me reanalyze the datasheet and notice Figures 15-1 and 15-4. Since OCR1A is TOP, a compare match is only generated when TCNT1 reaches OCR1A. Due to a successful compare match, OC1A is cleared and TCNT1 starts over at BOTTOM. However, based on my COM1A settings OC1A is immediately re-set at BOTTOM. This results in an identical situation as before the compare match was generated and basically nothing happens. // Mr. T pities me.

Post a Reply

Please log in to post a reply.

Did you know that binary numbers use base 2 to represent numbers, and these are important for understanding microcontroller registers? Learn more...