MCU: ATtiny2313
I use a hardware PWM pin to control the enable pin of a LED driver (constant current shift register). It works as expected, only that after reset all of the LEDs flash for a brief moment. The only explanation for this is that the enable line must be LOW for that period. Only I don't see where this happens. Initially all I/O lines are set as inputs, pull-up resistors enabled.
I've tracked down my problem to this piece of code, that is the initialization of the timer.
#include#include #include #include "led_driver.h" #include "system_ticker.h" #include "status_leds.h" // timer1 setup // // set prescaler to 8 for a PWM frequency of about 1kHz (F_CPU = 8000000) // TCCR1B &= ~(_BV(CS12) | _BV(CS10)); // TCCR1B |= _BV(CS11); // // set WGM mode 7: FAST PWM 10bit // TCCR1B &= ~_BV(WGM13); // TCCR1B |= _BV(WGM12); // TCCR1A |= (_BV(WGM11) | _BV(WGM10)); // // connect OC1A (PB3) to the PWM generator (wired to the /ENABLE pin of the led driver) // TCCR1A |= _BV(COM1A1); // TCCR1A &= ~_BV(COM1A0); // default value of TCCR1A: 00000000 #define TCCR1A_val ( _BV(WGM11) + _BV(WGM10) + _BV(COM1A1) ) // default value of TCCR1B: 00000000 #define TCCR1B_val ( _BV(CS11) + _BV(WGM12) ) void led_driver_setup(void) { DDRB |= _BV(PB3); // make OC1A (PB3) an output PORTB |= _BV(PB3); // set PB3 HIGH OCR1A = OCR1A_MAX; // compare match - 100% duty cycle - all off TCCR1A = TCCR1A_val; // doing it this way saves flash space ;-) TCCR1B = TCCR1B_val; }
If I don't call led_driver_setup() from main(), there is no erroneous flash.
If I read the datasheet correctly, the PWM cycle should start with OC1A as HIGH and drop to LOW once the compare match has occurred. As the code works as intended (except for the flash at startup), this assumption seems correct. I've also played with disabling interrupts while setting the TCCR1X registers, but that didn't change a thing.
Is there a special sequence to ensure that the first PWM cycle after reset doesn't glitch to LOW?