That's simple enough - you forgot that everything takes time.
Your timeline is:
- Configure timer
- Set count
- Wait for count to overflow (33 ticks)
- Toggle pin
- Do something with T1 (why...?)
- Clear overflow bit
- Go back to 1.
Here's how that looks as assembly:
90: 3b ef ldi r19, 0xFB
92: 42 e0 ldi r20, 0x02
94: 23 e0 ldi r18, 0x03
96: 91 e0 ldi r25, 0x01
while (1) {
98: 36 bd out 0x26, r19 ; TCNT0 = 0xFB;
9a: 14 bc out 0x24, r1 ; TCCR0A = 0X00;
9c: 45 bd out 0x25, r20 ; TCCR0B = 0x02;
while ( (TIFR0 & 0x01) == 0 );
9e: a8 9b sbis 0x15, 0
a0: fe cf rjmp .-4 ; 0x9e <setup+0xe>
PORTB ^= 0x03;
a2: 85 b1 in r24, 0x05
a4: 82 27 eor r24, r18
a6: 85 b9 out 0x05, r24
a8: 10 92 80 00 sts 0x0080, r1
ac: 10 92 81 00 sts 0x0081, r1
b0: 95 bb out 0x15, r25
}
b2: f2 cf rjmp .-28
So assuming that the waiting for the timer overflow takes 8*4+
1=33 clock cycles, and referencing the datasheet for how long each instruction takes, we can add up everything in the main while loop:
while (1) {
98: 36 bd out 0x26, r19 ; 1
9a: 14 bc out 0x24, r1 ; 1
9c: 45 bd out 0x25, r20 ; 1
while ( (TIFR0 & 0x01) == 0 );
9e: a8 9b sbis 0x15, 0 ; 2 (at end)
a0: fe cf rjmp .-4 ; 33 (while running)
PORTB ^= 0x03;
a2: 85 b1 in r24, 0x05 ; 1
a4: 82 27 eor r24, r18 ; 1
a6: 85 b9 out 0x05, r24 ; 1
a8: 10 92 80 00 sts 0x0080, r1 ; 2
ac: 10 92 81 00 sts 0x0081, r1 ; 2
b0: 95 bb out 0x15, r25 ; 1
}
b2: f2 cf rjmp .-28 ; 2
You can see that takes 48 clock cycles (We don't care about what is in the inner while
except when it comes to finishing, and that's just the SBIS
instruction). For 200kHz you want 40 clock cycles. You have 48. 16000000/48 = 333333. Divide by two for your pin toggling, and you get 166666Hz.
If you want to use this kind of method you need to ensure that the timer is completely free running and the overflow flag gets set at a regular interval, not just at 32 ticks after you start it.
You should be operating in CTC mode so it counts up from 0 to your target value and then resets back to 0 whilst setting the overflow flag. Your loop then looks like:
while (1) {
if ((TIFR0 & 0x01) == 0x01) {
PORTB ^= 0x03;
}
}
All the timer configuration is done before the loop and it just runs and runs until you say otherwise.