El LED AVR simple parpadea en el ensamblaje: ¿por qué no funciona este código?

He estado tratando de hacer parpadear un LED con ensamblaje AVR. Estoy usando un chip ATMega168 y una cadena de herramientas avr-gcc. Aquí está mi código:

.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

Calculo que mi LED debe estar encendido ~50% del tiempo (valores 0-127) y apagado el 50% del tiempo (valores 128-255). Pero no se enciende en absoluto (visiblemente).

Si ejecuto el programa en mi cabeza, es así.

  1. El contador TCNT0 comienza en cero
  2. el led esta encendido
  3. loopatraviesa sin bifurcarse haciadim
  4. lightsalta de nuevo aloop

Los pasos 3 y 4 ocurren en un ciclo para todos los valores de TCNT0 donde 0 <= TCNT0 <= 127, lo que significa que la luz está encendida todo este tiempo

  1. TCCR0B llega a 128, por lo que se ramifica para atenuar
  2. dimsalta de nuevo aloop

Los pasos 5 y 5 ocurren en un ciclo para todos los valores de TCNT0 donde 128 <= TCNT0 <= 255, lo que significa que la luz está apagada todo este tiempo

  1. Eventualmente, TCNT0 se desborda y volvemos a encender el LED nuevamente. Etcétera...

Suponiendo que la velocidad de mi reloj es de 8 Mhz (no sé cómo encontrar esto en la hoja de datos), el temporizador se incrementa una vez cada 1024 ciclos de reloj o aproximadamente 4 ms (10248 (1/8 ^ 6)). Lo que significa que mi LED debe estar encendido durante 512 ms (128 * 4) y luego apagado durante 512 ms.

Claramente, estoy haciendo algo mal aquí o la lógica anterior no es sólida, pero no estoy seguro de dónde.

Editar:

Si configuro la comparación para comparar con 255, parpadea. ¡Esto me confunde aún más!

Respuestas (1)

brgees una comparación mayor o igual con signo. El literal 128 de 8 bits es -128 en complemento a dos, que es el valor más bajo posible, por lo que TCNTsiempre será mayor y el LED permanecerá apagado. Intente usar brshen su lugar si desea usar valores sin firmar.

Por cierto, el literal 255 es -1 en complemento de dos, por lo que su código funciona correctamente cuando lo usa en su lugar.