Hallo zusammen,
ich hänge gerade an einem etwas kniffligem Assemblerprogramm...
An PortB und PortD sind LEDs angeschlossen und ich möchte nun so eine
wandernde "Snake" mittels Timer2 über die LEDs huschen lassen.
Die LEDs sind so angeordnet:
PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7
PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7
Und die Schlange sollte sich so bewegen:
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
dann
1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
dann
1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0
dann
0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
[usw]
0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0
dann
0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1
dann
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 1
dann
0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1
und so weiter. Am anderem Ende sollte sie wieder genau so umbrechen, wie
schon vorgezeigt. Das sollte sich dann so lange wiederholen, bis Timer2
gestoppt wird.
Ich habe versucht das Ganze mit 3 Registern zu lösen, aber noch läuft es
nicht wirklich, habe auch eben wieder alles gelöscht, was ich schon
hatte.
Hat einer von euch eine Idee, wie man das relativ eleganz umsetzen kann?
Ciao,
Roland
Kann man zweimal Rechtshift für negative machen? Wenn man zuerst 80
eingibt, und zweimal für negative shiftet, erhält man die Hexwerte
80->C0->E0. Dann normal nach rechts weiter shiften bis Übertrag ->Reg2.
Reg1 normal weitershiften, reg2 wieder negativ shiften, dann normal,
Übertrag nach reg1.
Ansonsten wäre das elganteste wohl 1 Register + Ladebefehle, z.B. mov 80
nach reg1 mov C0 nach reg1 usw oder eben die Werte aus dem Speicher oder
aus anderen Registern lesen.
Hi
>und warum nicht nur so?
Weil dann die 'Snake' teilweise nur 2 LEDs lang ist.
>xx:> rol r16> rol r17
Das Bit, das aus r17 ins Carry-Flag geschoben wird taucht erst beim
nächsten Durchlauf in r16 auf. Außerdem stimmt der Anfang nicht. Die
Vorgabe fängt nicht mit drei LEDs an.
MfG Spess
MOV r18,r16 ; War bei mir immer 0? Oder zu kurz debugged?
9
ANDI r18,0b10000000
10
11
OR r18,r19 ; Hier haben wir genau so oft 0b1000 0000
12
; stehen, wie Einsen im Anfangsmuster sind
13
14
LSL r20 ; Anfangsmuster wegrotieren, damit stoppt
15
; einmalige Einsengenerierung ("Softstart")
16
17
LSR r17 ; Eigentliche Rotation
18
19
OR r17,r18 ; Ab dem dritten mal ohne Einfluss
20
21
ROL r16 ; Verschwundene Einsen wieder auftauchen lassen
22
23
OUT PortB,r17 ; Ausgabe
24
OUT PortD,r16
25
RCALL Wartendasonstzuschnell
26
27
RJMP Loop
> Kurzer, knackiger Code! Ist sowas Kunst? :-)>> Gruß, Thomas>> PS: Kommentare hinter den Befehlen bitte als Hausaufgabe ... :-)
So in ETWA ist mir der Code jetzt klar. Habe mir ne Din A4-Seite
geschnappt und die Bitmuster Befehl für Befehl aufgeschrieben :-D
Wirklich sehr sehr clever, wie bist du auf diese Idee gekommen?
Damit hat Thomas das Rennen gemacht, dieser Snippet ist meinem Programm
gelandet :-D
Vielen Dank für eure fleißige Hilfe :-)
Roland Moch schrieb:> OR r17,r18 ; Ab dem dritten mal ohne Einfluss
Deine Kommentare sind leider nicht ganz korrekt.
Hier wird z.B. das Anfangsbitmuster (die ersten drei "1"-Bits), aber
auch das MSB der unteren Zeile eingesetzt. Und zwar immer! Nur nach dem
dritten Durchgang gibt es für das Anfangsbitmuster ausschließlich
"0"-Bits. Die MSB aus der unteren Zeile kommen jedoch immer wieder...
Du solltest dir den Code wesentlich länger im Debugger (Simulator)
anschauen...
Gruß,
Thomas
Das wäre nett. Ich hab zwar oben einige Kommentare geschrieben, aber ich
glaube die sind nicht alle 100%ig treffend.
Interessant wäre vielleicht auch dein Vorgehen gewesen, wie du auf diese
Idee gekommen bist.
Nochmal Danke und eine gute Nacht :-)
Philipp Klostermann schrieb:> Ich würde das so machen:> ...
Ist natürlich quatsch, da die LEDs links das LSB haben.
Also logisch umdrehen:
1
Anfang:
2
ldi r16,0
3
ldi r17,0
4
ldi r18,0
5
rcall AusgabeUndWarten
6
ldi r16,0b1
7
rcall AusgabeUndWarten
8
ldi r16,0b11
9
rcall AusgabeUndWarten
10
ldi r16,0b111
11
rcall AusgabeUndWarten
12
Scheife:
13
lsl r16 ; "rechtes" Bit (HSB) ins C-Flag,
14
ror r17 ; C-Flag von "links" in r17 übernehmen, "linkes" Bit von 17 ins
15
C-Flag
16
rol r18 ; Dieses in Bit 0 von r18 merken
17
lsr r16 ; nochmal nach "links", um
18
ror r18 ; das "linke" Bit aus r18
19
rol r16 ; beim "Rechts"-schieben zu übernehmen
20
rcall AusgabeUndWarten
21
rjmp Scheife
Habe das ganze gerade noch im Debugger getestet, und es scheint zu
funktionieren.
Ich frage mich nun, was an knibbels 9 Befehlen mit 5 involvierten
Registern, die zu verstehen und zu kommentieren einigen schwer zu fallen
scheint, so viel genialer (sorry: "knackiger") ist, als meine 6 Befehle,
die mit 3 Registern klar und einfach ein paar Bits rotieren. und nicht
mal einer Erwähnung wert zu sein scheinen. :-?
Hi
>Ich frage mich nun, was an knibbels 9 Befehlen mit 5 involvierten>Registern, die zu verstehen und zu kommentieren einigen schwer zu fallen>scheint, so viel genialer (sorry: "knackiger") ist, als meine 6 Befehle,>die mit 3 Registern klar und einfach ein paar Bits rotieren. und nicht>mal einer Erwähnung wert zu sein scheinen. :-?
Geht mir mit 4 Befehlen und 2 benutzten Registern auch so.
MfG Spess
OK, Du hast ein Register weniger, aber einen bedingten Sprung. Das mit
dem T-Flag ist natürlich eine Idee. :) Ich werde das mal im Hinterkopf
köcheln lassen.
Ich finde, dass sich die eigentliche Lösung zu vielen Threads irgendwo
mittendrin befindet, und unbeachtet in Flame-Wars oder gegenseitigem
Lobgehuddel anderer User untergeht. :D
Hey Leute,
ganz ganz ruhig. Ich hab eure Lösungen auch zu Kenntnis genommen und mir
überlegt sie einzubauen. Zumindest mit der Lösung von Spess ging es
nicht soo einfach (da müsste ich noch ein zusätzliches Register
einbauen), da ich das sonst mit meinem Timer nicht hinkriege.
Die 6 Befehle mit 3 Register sind bei mir SO auch nicht so einfach
unterzubringen, da ich keine AusgabeUndWarten-Funktion habe, sondern
einfach alles über den Timer machen will und da bräuchte ich dann auch
wieder ein Register und mehrere Branches, damit ich das benutzen kann.
Natürlich ist das alles kein Aufwand das so umzubiegen, aber wozu, wenn
Thomas Lösung quasi per Copy and Paste funktioniert...
Versteht mich nicht falsch, ich bin für jeden Beitrag dankbar ;-)
Roland Moch schrieb:> , da ich keine AusgabeUndWarten-Funktion habe, sondern> einfach alles über den Timer machen will und da bräuchte ich dann auch> wieder ein Register und mehrere Branches, damit ich das benutzen kann.
Die mehreren Branches brauchst Du nur, um den Ablauf am Anfang zu
realisieren. Ansonsten ist es doch egal, ob Du den Rumpf-Code in einer
Schleife hast, oder aus einer ISR heraus aufrufst. Wozu brauchst Du dann
ein zusätzliches Register? Als Flag, ob das Intro vorbei ist?
Hi
>Philipp Klostermann schrieb:>> Wozu brauchst Du dann>> ein zusätzliches Register? Als Flag, ob das Intro vorbei ist?>Ganz genau
Geht auch ohne.
MfG Spess
spess53 schrieb:>>Philipp Klostermann schrieb:>>> Wozu brauchst Du dann>>> ein zusätzliches Register? Als Flag, ob das Intro vorbei ist?>>>Ganz genau>> Geht auch ohne.
Und wie?
Worum geht es hier überhaupt noch? :-D
Also, da ihr mir keine Ruhe gelassen habt und ich die Erklärung mit der
Tabelle von Philipp so gut fand, hab ich mir die für mich logischste und
am einfachsten zu verstehende Lösung zusammengebastelt:
1
snake: ;(befindet sich im Timer-Interrupt)
2
mov temp, porb
3
add temp, pord
4
cpi temp, 4
5
brsh nointro
6
; Schlange aufbauen
7
com porb ; Eine 1 rein
8
lsl porb
9
com porb
10
out portB, porb
11
out portD, pord
12
rjmp exit
13
nointro:
14
lsl porb ; "rechtes" Bit (HSB) ins C-Flag,
15
ror pord ; C-Flag von "links" in r17 übernehmen, "linkes" Bit von 17 ins C-Flag
16
rol temp ; Dieses in Bit 0 von r18 merken
17
lsr porb ; nochmal nach "links", um
18
ror temp ; das "linke" Bit aus r18
19
rol porb ; beim "Rechts"-schieben zu übernehmen
20
21
out PortB, porb
22
out PortD, pord
23
rjmp exit
Um ehrlich zu sein, denke ich, dass ich mich jetzt lange genug mit
diesem Thema aufgehalten habe, nehmt es mir nicht übel ;-)
spess53 schrieb:> In dem du eine RAM-Zelle benutzt.
Oder so. :)
Roland M. schrieb:> Um ehrlich zu sein, denke ich, dass ich mich jetzt lange genug mit> diesem Thema aufgehalten habe, nehmt es mir nicht übel ;-)
Wir auch. Dann kannst Du noch die paar Minuten investieren, meine
abschließende Lösung zu inspizieren. :-)
Ich habe es jetzt wie folgt: (Debugger-getestet)
Das komplette Programm wäre nicht nötig gewesen ;-)
1
sec
2
rol r16
Das hab ich jetzt noch übernommen (also eigentlich fast gleich :-D)
Nochmals Danke an alle Antwortenden und ich denke wir sollten das Thema
jetzt ruhen lassen ;-)
Einen schönen, sonnigen Mittwoch an Alle :-)