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.
loop
läuft ohne Verzweigung durchdim
light
springt 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
dim
springt 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
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!
brge
ist ein vorzeichenbehafteter Größer-gleich-Vergleich. Das 8-Bit-Literal 128 ist -128 im Zweierkomplement, was der niedrigstmögliche Wert ist, also TCNT
wird es immer größer sein und die LED bleibt aus. Versuchen Sie es brsh
stattdessen 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.