Hallo Assemblerfreaks,
suche einen bestimmten Befehl und zwar:
in r16,PINB ;das läuft fehlerfrei, hier werden alle 8 Bits
ins Arbeitsregister r16 geladen.
Wie schaffe ich es, in r16 nur PINB,PB0 zu laden (oder PB7)
also nur ein Bitx
mit in oder ldi kommt Fehler!
Grüße
Rolf
mh...die bedingten Skipbefehle kenne ich aber!
sbic Skip, wenn Bit im PORT gelöscht ist, sbis gesetzt ist.
Und damit soll ich weiter kommen?
Mal sehen was daraus wird!
Rolf H. schrieb:> Wie schaffe ich es, in r16 nur PINB,PB0 zu laden (oder PB7)> also nur ein Bitx
Hängt davon ab, was mit den anderen 7 Bit in r16 passieren soll.
Ansonsten sind andi und ori deine Freunde...
Rolf H. schrieb:> Wie schaffe ich es, in r16 nur PINB,PB0 zu laden
Du kannst auch nach dem einlesen von PINB alle Bits, die du nicht
benötigst mit AND oder CBR ausmaskieren.
Rolf H. schrieb:> Und damit soll ich weiter kommen?
Was soll's denn werden? Irgendwas willst du mit dem Bit doch anstellen.
Großartige Berechnungen kann man da doch nicht machen. Bisschen Hin- und
Herschieben, Testen ob '0' oder '1'. Das war's.
Tip: Verwende eine Hochsprache oder lerne, das was du erreichen
möchtest, mit den gegebenen Assemblerbefehlen umzusetzen.
Das du mehr als einen Befehl brauchst, solltest du ja nun schon gemerkt
haben. Hast du einen guten Grund, Assembler einzusetzen? Deinem
Kenntnisstand nach zu urteilen würde ich sagen: Nein.
Rolf H. schrieb:> in r16,PINB ;das läuft fehlerfrei, hier werden alle 8 Bits> ins Arbeitsregister r16 geladen.
Macht ja nichts. Du kannst das gesuchte Bit mit BST (Bit Store)
zwischenspeichern und mit BLD (Bit Load) wieder zurückholen, und zwar in
jedes gewünschte Register an jede gewünschte Bit-Stelle.
Beispiel... Angenommen, du willst PINB7 an die Stelle des Bits 0 ins
Register r22 speichern:
1
in r16,PINB
2
bst r16,PINB7
3
bld r22,0
Du kannst auch in Abhängigkeit von dem zwischengespeicherten Bit
("T-Flag") verzweigen. Das geht mit den Befehlen BRTS und BRTC.
Ralf G. schrieb:> Rolf H. schrieb:>> Und damit soll ich weiter kommen?>> Was soll's denn werden? Irgendwas willst du mit dem Bit doch anstellen.> Großartige Berechnungen kann man da doch nicht machen. Bisschen Hin- und> Herschieben, Testen ob '0' oder '1'. Das war's.
an einem Tiny13 hängen 2 Taster gegen GND.
sw1 an PB3
sw2 an PB4
sowie 2 LEDs LEDrt an PB0, LEDgn an PB1
eine rcall Routine sieht so aus:
1
2
LED01:
3
in akku,PINB ; r16
4
lsl akku ; ein Bit nach links
5
swap akku ; tausche niederwertiges Byte mit höherwert.
6
com akku ; Komplement r16(LED leuchtet bei HIGH)
7
out PORTB,akku ;Ausgabe
8
ldi akku,(1<<PB3) | (1<<PB4)
9
out PORTB,akku ; Pull UP
10
ret
Und als ich mir in akku,PINB so betrachtete, kam mir die Idee
in r16 nur PINB,PB0 zu laden und glaubte, das mit einem Befehl
erschlagen zu können. Aber wie ich nun sehe, ist dem nicht so.
Die Idee von Jürgen
Rolf H. schrieb:> sw1 an PB3> sw2 an PB4
also willst du ja wohl die Bits letzten Endes abfragen. Oder nicht?
> Die Idee von Jürgen>
1
> in r16,PINB
2
> andi r16,1<<PINB0
3
>
> muss ich mal testen.
Ja, kann man machen.
Wenn du allerdings sowieso letzten Endes an der Stellung der schalter
interessiert bist und je nach Schalterstellung etwas machen willst, dann
hast du doch genau den Fall, dass du je nachdem, ob das Bit gesetzt oder
gelöscht ist, etwas ausführen oder eben nicht ausführen willst. Und
genau dafür sind ja die SBIS bzw. SBIC gedacht.
AVR-Tutorial: IO-Grundlagen
Jürgen W. schrieb:> Rolf H. schrieb:>> Wie schaffe ich es, in r16 nur PINB,PB0 zu laden>> Du kannst auch nach dem einlesen von PINB alle Bits, die du nicht> benötigst mit AND oder CBR ausmaskieren.>>
1
> in r16,PINB
2
> andi r16,1<<PINB0
3
>
>> Danach hast du nur noch Pinb0 in R16>> oder>
1
> sbic PINB,0
2
> ldi r16,1
3
>
4
> ...
5
>
bin weiter am experimentieren!
1
LED01:
2
in akku,PINB
3
andi akku,(1<<PINB3)
4
lsl akku ; ein Bit nach links
5
swap akku ; tausche niederwertiges Byte mit höherwert.
6
com akku ; Komplement r16
7
out PORTB,akku ;Ausgabe
8
ldi akku,(1<<PB3) | (1<<PB4)
9
out PORTB,akku ; Pull UP
10
ret
11
.EXIT
;in r16,PINB
;andi r16,1<<PINB3
; Ergebniss: sw1=LOW>>>>LEDrt und LEDgn leuchten, sw2=LOW>>>>nur LEDgn
leuchtet
das muss ich mir mal aufs Papier zeichnen, das wird nur das Ergebnis
durch lsl und swap sein.
zu Karl Heinz...das mit sbis bzw. sbic muß ich mir auch nochmal
durch den Kopf gehen lassen.
Eine Anwendung für die Frage liegt noch nicht vor, es war nur rein
eine Idee, ob es sowas wie xxx akku,PINB,PB3 giebt.
Aber ich sehe schon zwei Kommas in einer Befehlszeile, das kann nicht
sein.
Grüße
Rolf
Rolf H. schrieb:> das mit sbis bzw. sbic...
Die Skip-Befehle überspringen im Ja-Fall ja einen Befehl, der
sinvollerweise auch ein unbedingter Sprungbefehl sein kann. Ein
angenehmer Nebeneffekt ist dabei, dass die Skip-Befehle das SREG nicht
beeinflussen und somit auch nach der Skip-Verzweigung mittels
Branch-Befehlen auf Ereignisse (Flagzustände) vor der Verzweigung
reagiert werden kann.
Rolf H. schrieb:> ob es sowas wie xxx akku,PINB,PB3 giebt.
Hmmm, Du solltest Dir die Denkweise mit Akku, X und Y abgewöhnen, sie
passt nicht zur Architektur der AVRs und führt zu viel zu umständlichem
Denken. Die ALU der AVRs ist mit allen 32 Registern (bzw. 16 Registern
bei den Sechsbeinern) verknüpft, die (halbwegs) gleichwertig sind
(untere 16 können nicht mit Konstanten, oberste 6 können als Pointer
dienen).
Rolf H. schrieb:> das wird nur das Ergebnis> durch lsl und swap sein.
Bitverwurschteln mit Shift und Swap kann im Einzelfall sinnvoll sein,
ist aber sehr schlecht an sich ändernde Anforderungen anpassbar. Mit
BST/BLD bist Du besser beraten, das ist bedeutend flexibler und kann
ohne Mehraufwand an ziemlich alle Anforderungen angepasst werden.
...
Hallo Hannes Lux,
das mit BST +BLD habe ich mir mal angesehen. Es dauert, bis man es
begreift.
Als Beispiel mal:
bst r16,3 ;speichere Bit3 von r16 nach T-Bit des Statusregister
bld r17,0 ;lade Bit0 von r17 mit dem T-Bit
sehe ich das so richtig?
Ich habe aber 2 Tasten und wenn ich beide drücke, leuchten LEDrt+LEDgn
.....
Hi
>sehe ich das so richtig?
Ja.
>Ich habe aber 2 Tasten und wenn ich beide drücke, leuchten LEDrt+LEDgn
Dann musst du halt bst/bld für jedes Bit ausführen.
MfG Spess
Das ist der Lösungsansatz (falls ich verstanden habe, was du machen
willst):
Jürgen W. schrieb:> oder
1
> sbic PINB,0
2
> ldi r16,1
3
>
4
> ...
in deinem speziellen Fall:
1
; erstmal Grundzustand herstellen:
2
; entweder einfach alle LEDs aus oder entsprechend dem Einschalten mit
3
; 'sbic' auf losgelassene Taste testen
4
5
sbis PINB, 3
6
rcall LED1_einschalten
7
sbis PINB, 4
8
rcall LED2_einschalten
Der Aufruf von LEDx_einschalten kann im einfachsten Fall natürlich durch
das Setzen des entsprechenden 'LED-Bits' erfolgen. Ist ja auch nur ein
Befehl. Aber vielleicht soll die LED ja später mal blinken? ...
Rolf H. schrieb:> bst r16,3 ;speichere Bit3 von r16 nach T-Bit des Statusregister
Ja, das kopiert den Bitzustand von r16, Bit3 ins T-Flag.
>> bld r17,0 ;lade Bit0 von r17 mit dem T-Bit
Ja, das kopiert den Inhalt des T-Flags nach r17, Bit0.
>> sehe ich das so richtig?
Soweit ja.
> Ich habe aber 2 Tasten und wenn ich beide drücke, leuchten LEDrt+LEDgn
Mit dieser Aussage kann ich nichts anfangen, da ich nicht weiß, worauf
sie sich bezieht. Aber eigentlich ist es logisch, das beide LEDs
leuchten wenn beide Taster betätigt sind, vorausgesetzt, das jedem
Taster direkt eine LED zugeordnet ist.
Allerdings ist das Auswerten von Tastern eine etwas komplexere Sache
(Entprellung, Flankenerkennung, ...). Wenn die LEDs exakt den Eingängen
folgen sollen, dann braucht es keinen MC, dann kann man sie direkt
(natürlich über Widerstand) an den Taster anschließen... ;-)
Es heißt ja immer "E V A" (Eingabe, Verarbeitung, Ausgabe). Bei direkter
Zuordnung fehlt irgendwie die Verarbeitung, also braucht es da keinen
Controller...
Wenn Du (zu Lernzwecken) mit Tastern und LEDs hantieren willst, dann
entprelle die Taster, toggle damit Merker und lasse die LEDs bei aktivem
Merker blinken, möglichst jede mit einer anderen Frequenz. Was Du dabei
lernst, brauchst Du auch bei anderen AVR-Spielereien immer wieder.
...
Ich fang' mal oben an:
- besser auf nicht-gedrückte Taste testen, dann sparst du dir die
ganzen 'Zwischensprünge'
- welche Taste gedrückt wurde, hast du doch vor dem Aufruf von LED01
schon ausgewertet. Mach einfach noch LED02 dazu.
1
LED01:
2
sbi PORTB, PB0
3
ret
4
LED02:
5
sbi PORTB, PB1
6
ret
(Oder eben die 'Billigvariante' direkt unter dem Bittest)
Rolf H. schrieb:> ;hier bin ich am rumexperimentieren!
Das [ soll es zumindest ;-) ] überträgt den Zustand der Eingänge direkt
zu den Ausgängen:
1
START:
2
in r16, PINB ; Eingang abfragen
3
com r16 ; invertieren
4
and r16, 0x18 ; maskieren
5
lsl r16 ; positionieren
6
swap r16
7
in r17, PORTB ; Portzustand einlesen
8
and r17, 0x03 ; Ausgang löschen
9
or r17, r16 ; beschreiben
10
out PORTB, r17 ; und raus damit
11
rjmp START
Da kannst du dir sämtliche Jumps und Calls vorher sparen.
Aber, das ist nicht das, was man will. Sondern Ein- und Ausgabe schön
getrennt, damit das erweiterbar bleibt.
Hallo Ralf,
ich habe Deine beiden Vorschläge hier ausgedruckt vor mir,
und werde sie geistig mal verarbeiten.
Natürlich unter einer neuen xx.asm Datei, denn die umständliche läuft
ja wie ich es wollte.
Danke nochmals...lass von mir hören!
Grüße
Rolf
so funzt es wie gehabt!
warte:
sbic sw1 ; Skip nach rcall, wenn PB3=LOW
rjmp gehe01 ; Skip nach gehe01, wenn PB3=HIGH
rcall LED01
gehe01:
sbic sw2 ; Skip nach rcall, wenn PB4=LOW
rjmp warte ; Skip nach warte, wenn PB4=HIGH
rcall LED02
rjmp loop
LED01:
sbi PORTB,PB0
ret
LED02:
sbi PORTB,PB1
ret
Jetzt geht's an sbic...da schreibst Du, besser auf nicht gedrückte Taste
testen, dann spare ich die ganzen Zwischensprünge...o weia!
Soll ich sbis nehmen?
sbic -> Überspringe, wenn Bit im IO-Register gelöscht ist.
Wann ist das Bit gelöscht? - Wenn die Taste gedrückt ist.
Du machst sowas hier:
Wenn Taste losgelassen, dann mache erstmal nichts, sondern springe
weiter hinten ins Programm. Falls aber die Taste gedrückt ist, dann mach
die LED an.
Verstanden? ;-)
Einfacher ist:
Wenn die Taste gedrückt ist, schalte LED. (Weiter geht's automatisch.)
1
sbis PORTB, PB3 ; wenn Taste losgelassen, nächsten überspringen
2
rcall LED0
3
sbis PORTB, PB4 ; wenn Taste losgelassen, nächsten überspringen
4
rcall LED1
5
6
; das lässt sich jetzt beliebig erweitern:
7
; sbis PORTB, PBx ; wenn Taste losgelassen, nächsten überspringen
Hallo Ralf,
erst heute Abend komme ich dazu Deine Änderung mit sbis geistig
zu verarbeiten. Das kommt davon, wenn man zu viele Hobbys hat.
So sieht es jetzt aus...ich weiss nicht, ob ich das alleine hin-
bekommen hätte.
Habe es gleich ausgedruckt, denn so was kann ich bestimmt für
Modelleisenbahn verwenden.
loop:
cbi PORTB,PB0
cbi PORTB,PB1
sbis sw1 ; Überspringe nach sbis sw2, wenn PB3=1
rcall LED01 ; Skip nach LED01, wenn PB3=0
sbis sw2 ; Überspringe nach rjmp loop, wenn PB4=1
rcall LED02 ; Skip nach LED02, wenn PB4=0
rjmp loop
LED01:
sbi PORTB,PB0
ret
LED02:
sbi PORTB,PB1
ret
Meinen Dank nochmals, habe wieder viel gelernt!
Grüße
Rolf