2
\$\begingroup\$

I'm using an ATtiny85 to generate a PWM output (using Timer0 in OCR mode), and this PWM output is being switched on and off at regular intervals. I am finding that when switching on the PWM output, there is a delay before it actually starts outputting.

Look at the screenshot below, the green line shows the state I am putting the PWM into (either on or off via TCCR1) and yet there is a delay of what looks like one full cycle before it starts. I've tried also resetting TCNT0 to 0, but this had no effect.

Enter image description here

(Timebase is 20 µs.)

SET(DDRB, PB1);
SET(DDRB, PB2);

// Set up PWM for 460 kHz with 8 MHz clock
TCCR1 = (1<<PWM1A) | (1<<COM1A1) | (1<<COM1A0) | (1<<CS10); // Prescaler = none;
GTCCR = (1<<FOC1A);
OCR1A = 9; // 460.750 kHz
OCR1C = 18;

#define BIT_DELAY ((1000000/38400))

while(1) {
    SET(TCCR1, PWM1A);
    SET(PORTB, PB2);
    _delay_us(BIT_DELAY);
    CLR(TCCR1, PWM1A);
    CLR(PORTB, PB2);
    _delay_us(BIT_DELAY);
}
\$\endgroup\$
  • \$\begingroup\$ Can you please share the code snippet \$\endgroup\$ – anishkumar Mar 5 '16 at 16:16
  • \$\begingroup\$ yep added, thanks! One pin is the green and the other is the timer output \$\endgroup\$ – user3780104 Mar 5 '16 at 16:23
2
\$\begingroup\$

Disabling the PWM mode of TIMER1 does not stop TCNT from counting - it only stops the PWM from being output.

So when you disable the output using CLR(TCCR1, PWM1A), TCNT1 keeps merrily counting along and does not reset to 0 when it hits OCR1C since it is not in PWM mode anymore. It runs right past OCR1C and will keep on counting up to 255 when it rolls over.

The delay you are seeing is the time it take TCNT1 to count from where ever it happens to be when you enable PWM mode back to OCR1C, at which time it will reset to 0 and start doing a normal PWM cycle.

One way to control when the PWM cycle starts after you enable PWM mode is to preload the counter such that it will not have to do a wrap around before starting the normal PWM compare points in OCR1A and then OCR1C. For example...

    while(1) {
        TCNT1=254;
        SET(TCCR1, PWM1A);
        SET(PORTB, PB2);
        _delay_us(BIT_DELAY);
        CLR(TCCR1, PWM1A);
        CLR(PORTB, PB2);
        _delay_us(BIT_DELAY);
    }

... generates this waveform...

enter image description here

Note that this approach seems like a hack to me and that there are probably better ways to gate the PWM signal that would more straightforward, but the best choice would depend on your application.

\$\endgroup\$
  • \$\begingroup\$ thanks. Would have never noticed the ocr1c compare was being disabled too! \$\endgroup\$ – user3780104 Mar 19 '16 at 21:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.