Atmega32U16 - PWM - No output

Guest #6245132
Rate this post
• ▲ useful
▼ not useful
Dear friendly,

I am currently trying to dim LEDs by applying PWM on the LEDs' supply 
voltage.
My setup is:
- Atmega32U16
- usbasp Programmer (chinese)
- 16 MHz external crystal
- hfuse c9, lfuse 3f
- External interrupts on INT0, INT1, INT2
- Use of Timer0 for more sophisticated interrupt handling

Here's the relevant part of my init code (for whole main see bottom):
1
int main(void) {
2
    ...
3

4
    // use OC1B as output, Pin D4
5
    DDRD |= (1 << PD4);
6

7
    // non-inverted output, toggle OC1B on compare match
8
    TCCR1A |= (1 << COM1B0) | (1 << WGM10) | (1 << WGM11);
9

10
    // select OCR1B is TOP for WGM10:3 == 1; detemine counting sequence
11
    TCCR1B = (1 << WGM12) | (1 << WGM13);
12

13

14
    OCR1B = 0; // toggle on TCNT1 == 0
15
    OCR1A = 7811; // set TOP value for PWM1A, toggle on TCNT1 = 7811
16

17
    // select prescaler 1024, start timer
18
    TCCR1B |= (1 << CS12) | (1 << CS10);
19

20
    ...
21

22
    for(;;) { ... }
23

24
    return 0;
25
}

This should imo produce a pulsed output with a frequency 1Hz on port 
OC1B. Thus, if I connected a LED to Pin D4, it should toggle every 1 
second.
BUT, sadly, that does not happen. I'd very much appreciate any advice on 
how to make it work.
[c]
int main(void) {
    // CTC mode Timer0
    TCCR0 |= (1 << WGM01);
    // select prescaler 1024
    TCCR0 |= (1 << CS00) | (1 << CS02);
    // interrupt @625Hz
    OCR0 = 25 - 1;
    // use internal CPU interrupt vector
    TIMSK |= (1 << OCIE0);

    // activate OC1B as outputs (PIN D4)
    DDRD |= (1 << PD4);

    // non inverted output, toggle on compare match
    TCCR1A |= (1 << COM1B0) | (1 << WGM10) | (1 << WGM11);
    // select OCR1B is TOP for WGM10:3 == 1; detemine couting sequence

    TCCR1B = (1 << WGM12) | (1 << WGM13);

    // set TOP value for PWM1A
    OCR1B = 0;
    OCR1A = 15383;//PWM_MAX-1;

    // select prescaler 1024
    TCCR1B |= (1 << CS12) | (1 << CS10);

    // select external interrupts INT0, INT1, INT2
    MCUCR = (1 << ISC01) | (1 << ISC11);

    // enable fetching interrupts
    GICR |= (1 << INT0) | (1 << INT1) | (1 << INT2);

    // enable interrupt service routines
    sei();

    DDRC |= 0xff;

    for (;;) {
        PORTC++;
        _delay_ms(50);
    }

    return 0;
}
[\c]
Guest #6245271
Rate this post
• ▲ useful
▼ not useful
Found the solution. The datasheet says

"WGM13:0 = 15: Toggle OC1A on Compare Match, OC1B disconnected (normal 
port operation)."
That is why
1
DDR |= (1 << PD4); // This would activate disconnected OC1B
2
TCCR1A |= (1 << COM1B0) ...; // cannot toggle disconnected Pin OC1B
does not make much sense. Fixed this by using PD5 and (1 << COM1A0):
1
    DDRD |= (1 << PD5);
2

3
    // non inverted output, toggle on compare match
4
    TCCR1A |= (1 << COM1A0) | (1 << WGM11) | (1 << WGM10);
5
    // select OCR1B is TOP for WGM10:3 == 1; detemine counting sequence
6
    TCCR1B |= (1 << WGM12) | (1 << WGM13);
7
    // select prescaler 1024
8
    TCCR1B |= (1 << CS12) | (1 << CS10);
9

10
    OCR1A = TOP-1;

Reply

Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.

Formatting
  • [c]C-Code[/c]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]
  • [[Title]] – link to an article
  • Link to another post: right-click its post ID (#8078628), copy the address, paste it into the text

More about formatting

Post long source code as an attachment, not in the text.

Already registered? Log in

Not shown to anyone. We send you a link; your post appears once you confirm it there.

By submitting you create a free account and accept the terms of use.