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
loopruns through without branching to
lightjumps back to
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
dimjumps back to
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.
If I set the comparison to compare with 255, it does blink. This confuses me even more!