Forum: Mikrocontroller und Digitale Elektronik suche in Assembler einen bestimmten Befehl!


von Rolf H. (flash01)


Lesenswert?

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

von Tim  . (cpldcpu)


Lesenswert?

Schaue Dir mal die Beschreibung von SBIC und SBIS an. Ansonsten brauchst 
Du mehr als einen Befehl.

von Rolf H. (flash01)


Lesenswert?

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!

von Sven P. (Gast)


Lesenswert?

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...

von Jürgen W. (juergen_w) Benutzerseite


Lesenswert?

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

Danach hast du nur noch Pinb0 in R16

oder
1
sbic PINB,0
2
ldi r16,1
3
4
...

von Ralf G. (ralg)


Lesenswert?

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.

von Rolf H. (flash01)


Lesenswert?

danke für Eure Antworten, erst mal das schöne Wetter nutzen, melde mich!

: Bearbeitet durch User
von Matthias Larisch (Gast)


Lesenswert?

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.

1
r16 = r16 & ~(1 << PB0) | PINB & (1 << PB0)

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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.

von Rolf H. (flash01)


Lesenswert?

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
1
in   r16,PINB
2
andi  r16,1<<PINB0
muss ich mal testen.

Grüße

Rolf

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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

: Bearbeitet durch User
von Rolf H. (flash01)


Lesenswert?

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

: Bearbeitet durch User
von Hannes L. (hannes)


Lesenswert?

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.

...

von Rolf H. (flash01)


Lesenswert?

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

.....

von spess53 (Gast)


Lesenswert?

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

von Ralf G. (ralg)


Lesenswert?

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? ...

von Hannes L. (hannes)


Lesenswert?

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.

...

von Rolf H. (flash01)


Lesenswert?

am besten, ich schiebe den gesamten Code mal rüber, dann wird es
verständlicher!

; Projekt-Name: Projekttiny13                      Datum: 25.10.2013

; Datei: Taste-LED05.asm

; Option: bei gedrückter Taste sw1 (an PB3)leuchtet LEDrt (an PB1)
;         bei gedrückter Taste sw2 (an PB4)leuchtet LEDgn (an PB0)

; AVR: Tiny13-20PU

  .INCLUDE   "tn13def.inc"     ; Deklaration für Tiny13
  .EQU       takt = 1000000    ; Systemtakt 1,0 MHz

  .def    akku=r16
  #define sw1  PINB,PB3
  #define sw2  PINB,PB4


  rjmp    start             ; Reseteinsprung

  start:                    ; Vorbereitung

  ldi      akku, (1<<PB1) | (1<<PB0)
  out      DDRB,akku        ; PB1,PB0 = Output

  ldi      akku, (1<<PB3) | (1<<PB4)
  out      PORTB,akku       ; PB3,PB4 = Pull Up


  loop:
  cbi      PORTB,PB0 ;bei loslassen der Tasten sollen die LEDs
  cbi      PORTB,PB1 ;wieder dunkel werden.
;ein Prellen der Tasten ist nicht erkennbar.
  warte:
  sbic     sw1              ; Überspringe nach rcall, wenn PB3=LOW
  rjmp     gehe01           ; Skip nach gehe01, wenn PB3=HIGH
  rcall    LED01

  gehe01:
  sbic     sw2              ; Überspringe nach rcall, wenn PB4=LOW
  rjmp     warte            ; Skip nach warte, wenn PB4=HIGH
  rcall    LED01
  rjmp     loop

  LED01:
  in       akku,PINB        ;hier bin ich am rumexperimentieren!
  lsl      akku             ; ein Bit nach links
  swap     akku             ; tausche niederwertiges Byte mit höherwert.
  com      akku             ; Komplement r16 (wenn 1 >>LED=EIN)
  out      PORTB,akku       ;Ausgabe
  ldi      akku,(1<<PB3) | (1<<PB4)
  out      PORTB,akku       ; Pull UP
  ret
 .EXIT

von Alex W. (a20q90)


Lesenswert?

Ralf G. schrieb:
> Rolf H. schrieb:
>> Und damit soll ich weiter kommen?
>
> Was soll's denn werden?

Ein Mädchen :-)

von Ralf G. (ralg)


Lesenswert?

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)

von Ralf G. (ralg)


Lesenswert?

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.

von Rolf H. (flash01)


Lesenswert?

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

von Rolf H. (flash01)


Lesenswert?

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?

von Ralf G. (ralg)


Lesenswert?

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    
8
;  rcall IrgendwasEinschaltenOderAusgeben
9
;  ...

von Rolf H. (flash01)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.