Hallo Leute
Wollt mir mit meinem STK500 und mienem ATMega8515 ein Lauflicht basteln.
Da dies aber nicht so funktionierte wie ich wollte, hab ich mich
entschlossen zuerst mal die LED's blinken zu lassen, da dies einfacher
ist.
Beim ersten versuch mit folgendem code hats nicht geklappt:
//Codebeginn
.include "8515def.inc"
;PortB als ausgang deginieren
ser r16
out DDRB, r16
ser r18
Main:
ldi r16, 0xFF
out PortB, r16
Loop1:
dec r18
brne Loop1
clr r16
ldi r16, 0x00
out PortB, r16
Loop2:
dec r18
brne Loop2
rjmp Main
//Codeende
als ich dann aber dec r18 durch sbiw r30, 1 ersetzt habe, funktionierte
es.
Ich frage mich aber warum? bei dec r18 wird doch von 0xFF bis 0x00
runtergezählt bevor weitergemacht wird. Bei sbiw wird doch vom r30
welches mit 0xFF geladen ist immer eins abgezogen, bis es ebenfalls auf
0x00 ist. Seh ich das falsch? denn in meinen augen sollte beides das
selbe bewirken.
So nun hab ich mienen zuvor erstellten Lauflichtcode ebenfalls mit sbiw
"erweitert" jedoch passiert nun nichts anderes, als dass ein led nach
dem andern zu leuchten anfängt, bis alle leuchten.
//Codeanfang
.include "8515def.inc"
ser r16
out ddrb, r16
ldi r16, 0xFF
Main:
sbiw r30, 1
brne main
ror r16
out PortB, r16
sbiw r30, 1
brne main
rjmp main
//Codeende
Was mache ich falsch?
Hoffe ihr könnt mir meine beiden fragen beantworten;)
Gruss
Sheester
dec dekrementiert ein Register, zählt also eins ab. sbiw zählt von einem
RegisterPAAR eins ab. Dein Blinklicht sollte schon mit dem ersten Code
funktionieren, allerdings blinkt das so schnell, dass du es nicht
siehst. Wenn du da jetzt sbiw reinhaust, dekrementierst du damit einen
16-Bit-Wert und deine Schleife läuft damit nicht nur 256, sondern 65536
Takte lang. Das wirst du schon eher wahrnehmen können.
Für sowas solltest du aber einen Timer verwenden (Siehe Tutorial und
Datenblatt).
Dein Lauflicht hat einige Fehler drin:
1. Deine zweite Schleife ist Blödsinn (Die springt ja sofort wieder zu
main, da wird also gar keine Zeit vertrödelt).
2. Nach brne main ist in jedem Fall das Carry-Bit gesetzt, was ror dazu
veranlasst, eine 1 in das Register zu schieben. Wenn du das nicht willst
musst du entweder lsr (logical shift right) verwenden oder aber vor dem
schieben noch clc (clear carry) ausführen.
3. Sobald du einmal ganz durchgeschoben hast ist das Register leer, bzw.
voll, dann passiert beim Schieben nix mehr. Du solltest also nach dem
Schieben prüfen, ob das Carry-Bit gesetzt ist (Ist der Fall wenn ein Bit
"rausfällt") und dieses dann gleich wieder reinschieben.
Z.B.
Weiterhin benutzt du die falsche Includedatei..
Die 8515def.inc ist für den AT90S8515, du brauchst die m8515def.inc.
Noch mag es gehen aber wenn du mehr machen willst kann sowas die
absurdesten Fehler machen dank falscher I/O-Adressen.
Gruß,
Christian
Vielen dank für die schnelle antwort
Also das mit der schlaufe hab ich geändert, war wirklich sinnlos;)
nun hab ich die weiteren tipps versucht umzusetzen, jedoch nicht
wirklich mit erfolg.
Also ich hab mal ne grundätzliche frage zum befehl ror bzw rol.
Ich fülle ein register mit dem wert 0xFE das entspricht ja 11111110
Da beim board ja die LED's bei 0 leuchten leuchtet nur das Bit bzw LED
0.
Soweit sogut. Wenn ich doch jetzt den befehl rol für das mit 0xFE
gefüllte register andwende, sollte doch nichts anderes geschehen ausser
dass alle bits nach links geschoben werden oder? das heisst es steht nun
11111101 im register, oder seh ich das falsch? Also müsste doch nun das
LED 1 leuchten. Wenn ich aber das Programm durchlaufen lassen, fängt
eines nach dem anderen zu leuchten an...
Hoffe ihr könnt miene unklarheiten bzw. eventuelle fehlinterpretationen
beseitigen.
Sheester wrote:
> Also ich hab mal ne grundätzliche frage zum befehl ror bzw rol.> Ich fülle ein register mit dem wert 0xFE das entspricht ja 11111110> Da beim board ja die LED's bei 0 leuchten leuchtet nur das Bit bzw LED> 0.
So weit noch richtig...
>> Soweit sogut. Wenn ich doch jetzt den befehl rol für das mit 0xFE> gefüllte register andwende, sollte doch nichts anderes geschehen ausser> dass alle bits nach links geschoben werden oder?
So weit auch noch im Prinzip richtig...
> das heisst es steht nun> 11111101 im register, oder seh ich das falsch?
Das siehst Du tatsächlich falsch. Es werden zwar alle Bits im Register
nach links geschoben. Allerdings wird das höchstwertige Bit (also das
ganz links) ins Carry-Flag geschoben und das, was vorher im Carry stand,
wird von rechts ins Register reingeschoben. Wenn im Carry aber vorher ne
Null stand, dann wird von hinten auch eine Null reingeschoben. Konkret:
C Register
0 11111110
rol -> 1 11111100
usw...
Das Carry ist vor dem rol nur dann gesetzt, wenn bei der vorhergehenden
Operation ein Überlauf aufgetreten ist.
> Also müsste doch nun das> LED 1 leuchten. Wenn ich aber das Programm durchlaufen lassen, fängt> eines nach dem anderen zu leuchten an...
Und das ist dann der Effekt davon.
EDIT:
Wenn Du mal in die Befehlssatz-Dokumentation schaust (entweder das
Pamphlet mit dem Titel "Instruction Set Manual" von der ATMEL-Homepage
oder die AVRStudio-Hilfe), dann steht da bei dem Befehl rol die
Beschreibung "rotate left through carry" und weiter unten ist auch ein
schönes Bildchen von der Prozedur. Das sollte eigentlich keine Fragen
offenlassen.
Sry, da hatte ich mich oben wohl geirrt. Ich dachte, du willst eine
einzelne 1 durchschieben, nicht einen 0. Ich ziehe es jedoch vor, LED
EIN als 1 zu betrachten und erst direkt vor der Ausgabe die Daten mit
com rxx umzudrehn.
1
;...
2
ldi r16, 1
3
loop:
4
lsr r16
5
brcc loop_a
6
sbr r16, 128
7
loop_a:
8
9
;Bits umdrehen und ausgeben
10
com r16
11
out PORTB, r16
12
;Und wieder zurückdrehen, damit es nachher wieder aufgeht
13
com r16
14
15
;Mach mal 'ne Pause...
16
rcall delay_100ms
17
rjmp loop
18
;...
Das könnte irgendwie so aussehn. Zugegeben, das doppelte umkehren ist
etwas sinnlos, aber auf das kommt es im Allgemeinen ja nicht an. Falls
doch:
1
;...
2
ldi r16, 254
3
loop:
4
sec ;Carry setzen, sonst wird eine 0 reingeschoben
5
ror r16
6
brcs loop_a
7
cbr r16, 128
8
loop_a:
9
10
out PORTB, r16
11
12
;Mach mal 'ne Pause...
13
rcall delay_100ms
14
rjmp loop
15
;...
Ist alles ungetestet.
Achja, diese Variante funktioniert auch mit anderen Mustern als
einzelnen LEDs.