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

1

He estado intentando parpadear un LED con el ensamblaje de 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

Me imagino que mi LED debería estar encendido ~ 50% del tiempo (valores 0-127) y apagado el 50% del tiempo (valores 128-255). Pero no se ilumina (visiblemente).

Si ejecuto el programa, aunque mi cabeza sea así.

  1. El contador TCNT0 comienza en cero
  2. el LED está encendido
  3. loop se ejecuta sin bifurcar hasta dim
  4. light salta de nuevo a loop

Los pasos 3 y 4 ocurren en un bucle para todas las ventas 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 las ramas se atenúan
  2. dim salta de nuevo a loop

Los pasos 5 y 5 suceden en un bucle para todas las ventas 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. Y así sucesivamente ...

Suponiendo que mi velocidad de reloj es de 8Mhz (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 debería estar encendido durante 512 ms (128 * 4) y luego apagado durante 512 ms.

Claramente, me estoy equivocando de algo aquí o la lógica anterior no es sólida, pero no estoy segura de dónde.

Editar:

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

    
pregunta Matt Harrison

1 respuesta

2

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

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

    
respondido por el Jon

Lea otras preguntas en las etiquetas