Using an AVR timer to generate a 38 kHz signal

avrcdelaymicrocontrollertimer

I need a 13 microseconds delay for transmitting IR at a 38 kHz carrier wave. My chip (ATtiny84) is running at 8 MHz. I cannot figure out what's the problem is in my code:

void send(long microsecs)
{
    TCCR0B |= (1 << CS00); // Enable Timer 0 - No prescale

    while (microsecs > 0)
    {
        // 38 kHz is about 13 microseconds high and 13 microseconds low
        PORTB |= (1 << PB2); // 3 µs
        TCNT0 = 0;
        while (TCNT0 < 104);

        PORTB &= ~(1 << PB2);   // 3 µs
        TCNT0 = 0;
        while (TCNT0 < 104);

        // So 26 microseconds altogether
        microsecs -= 26;
    }
}

The delay (104 clock cycles) sums up to 13 microseconds @8 MHz and the while loop should hang up the code for the required time period, but it's not working.

But

When I replace this:

   TCNT0 = 0;
   while (TCNT0 < 104);

by this:

_delay_us(13);

everything works fine.

If I'm doing something wrong, please point out.

Best Answer

You are not updating PB2, you set it high in the 1st delay and then you set it high again in the second delay, switch from PORTB |= (1 << PB2); to PORTB &= ~(1 << PB2); in one of the delays