I've been trying to blink an LED with AVR assembly. I'm using an ATMega168 chip and avr-gcc toolchain. Here's my code:
.include "m168.h"
.global main
main:
ldi r16, 0b00000001
out DDRB,r16 ; Set PB0 to output
out PORTB,r16 ; Set PB0 high
ldi r16, 0b00000101
out TCCR0B,r16 ; Set prescaler to 1024
loop:
in r17, TCNT0 ; If the counter is >= 128,
cpi r17, 128 ; branch to dim
brge dim ; otherwise continue to light
light:
sbi PORTB, 0
rjmp loop
dim:
cbi PORTB,0
rjmp loop
I figure that my LED should be on ~50% of the time (values 0-127) and off 50% of the time (values 128-255). But it doesn't light at all (visibly).
If I run the program though my head it goes like this.
- Counter TCNT0 starts at zero
- LED is on
loop
runs through without branching todim
light
jumps back toloop
Steps 3 and 4 happen in a loop for all vales of TCNT0 where 0 <= TCNT0 <= 127, meaning the light is on all this time
- TCCR0B reaches 128, so branches to dim
dim
jumps back toloop
Steps 5 and 5 happen in a loop for all vales of TCNT0 where 128 <= TCNT0 <= 255, meaning the light is off all this time
- Eventually TCNT0 overflows, and we go back to the LED being on again. And so on...
Assuming my clock speed is 8Mhz (don't know how to find this in the datasheet), the timer increments once every 1024 clock cycles or roughly 4ms (10248 (1/8^6)). Which means my LED should be on for 512ms (128 * 4) and then off for 512ms.
Clearly I'm getting something wrong here or logic above isn't sound but I'm not sure where.
Edit:
If I set the comparison to compare with 255, it does blink. This confuses me even more!