Einfaches AVR-LED-Blinken in der Montage - warum funktioniert dieser Code nicht?

Ich habe versucht, eine LED mit AVR-Baugruppe zu blinken. Ich verwende einen ATMega168-Chip und eine avr-gcc-Toolchain. Hier ist mein 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

Ich schätze, dass meine LED ~ 50 % der Zeit (Werte 0-127) und 50 % der Zeit (Werte 128-255) aus sein sollte. Aber es leuchtet überhaupt nicht (sichtbar).

Wenn ich das Programm durch meinen Kopf laufen lasse, geht es so.

  1. Der Zähler TCNT0 beginnt bei Null
  2. LED ist an
  3. loopläuft ohne Verzweigung durchdim
  4. lightspringt zurück zuloop

Die Schritte 3 und 4 erfolgen in einer Schleife für alle Werte von TCNT0, wobei 0 <= TCNT0 <= 127 ist, was bedeutet, dass das Licht die ganze Zeit an ist

  1. TCCR0B erreicht 128, verzweigt also zu dimmen
  2. dimspringt zurück zuloop

Die Schritte 5 und 5 erfolgen in einer Schleife für alle Werte von TCNT0, wobei 128 <= TCNT0 <= 255 ist, was bedeutet, dass das Licht die ganze Zeit aus ist

  1. Schließlich läuft TCNT0 über und wir kehren zu der LED zurück, die wieder an ist. Usw...

Angenommen, meine Taktrate beträgt 8 MHz (ich weiß nicht, wie ich das im Datenblatt finden kann), erhöht sich der Timer alle 1024 Taktzyklen oder ungefähr 4 ms (10248 (1/8 ^ 6)). Das bedeutet, dass meine LED für 512 ms (128 * 4) an und dann für 512 ms aus sein sollte.

Offensichtlich mache ich hier etwas falsch oder die obige Logik ist nicht stichhaltig, aber ich bin mir nicht sicher, wo.

Bearbeiten:

Wenn ich den Vergleich auf Vergleich mit 255 setze, blinkt es. Das verwirrt mich noch mehr!

Antworten (1)

brgeist ein vorzeichenbehafteter Größer-gleich-Vergleich. Das 8-Bit-Literal 128 ist -128 im Zweierkomplement, was der niedrigstmögliche Wert ist, also TCNTwird es immer größer sein und die LED bleibt aus. Versuchen Sie es brshstattdessen mit, wenn Sie vorzeichenlose Werte verwenden möchten.

Übrigens ist das Literal 255 -1 im Zweierkomplement, weshalb Ihr Code korrekt funktioniert, wenn Sie es stattdessen verwenden.