EmbDev.net

Forum: µC & Digital Electronics Atmega32U16 - PWM - No output


von LustigerGeselle (Guest)


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]

von LustigerGeselle (Guest)


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;

von c-hater (Guest)


Rate this post
useful
not useful
LustigerGeselle wrote:

> Found the solution.

Congrats

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.