Forum: Mikrocontroller und Digitale Elektronik Assembler Syntax-Frage eines Anfängers


von Jan Purrucker (Gast)


Lesenswert?

Hallo allerseits,

ich habe hier im Forum vor kurzem folgende Beispiel-Routine für eine
ADC Wandlung am AVR bekommen:


ADCRead:
  sbis  ADCSRA,ADEN
  rjmp  ADCEnable
  sbic  ADCSRA,ADSC
  ret
  in  r16,ADCL
  in  r17,ADCH
  sts  ADCVal,r16
  sts  ADCVal+1,r17
  sbi  ADCSRA,ADSC
  ret
ADCEnable:
  ldi r18,0b01<<REFS0|0<<ADLAR|0b00000<<MUX0
  out ADMUX,r18
  ldi r18,1<<ADEN|1<<ADSC|0b0111<<ADPS0
  out ADCSRA,r18
  ret



Soweit habe ich alles fleißig analysiert und nachvollzogen. Leider habe
ich allderdings noch nicht ganz kapiert, welche Vorgänge bei folgenden
Zeilen passieren, und warum sie so sinnvoll sind:
"ldi r18,0b01<<REFS0|0<<ADLAR|0b00000<<MUX0"
und
"ldi r18,1<<ADEN|1<<ADSC|0b0111<<ADPS0"

Könnte mir hier jemand im Klartext mitteilen was es mit diesen Zeilen
auf sich hat (z.B. 0b00000<<ASPS0 ??)?
Vielen Dank schon mal.

Gruß
Jan Purrucker

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Diese "shift-Schreibweise" ist bei den Programmierern in diesem Forum
aus mir nicht nachvollziehbaren Gründen äußerst beliebt.

Die Konstanten ADEN, ADSC etc. sind numerische Werte, die die Nummer
eines Bits in einem Register angeben.

Mit "1 << ADEN" wird ein Wert erzeugt, der einer 1 in dem
betreffenden Register entspricht.

Mal angenommen, ADEN wäre 4, wird "1 << ADEN" also ersetzt durch "1
<< 4", was also 16 bzw. 0x10 enspricht.

"0b0111 << ADSP0" bedeutet, daß der Wert 7 um eine bestimmte Anzahl
an  Bits verschoben wird; angenommen, daß ADSP0 2 wäre, entspräche das
Konstrukt also

"7 << 2", was wiederum 0x1C enspricht.

Was sich der findige Programmierer beim Konstrukt

"0b01<<REFS0|0<<ADLAR|0b00000<<MUX0"

gedacht hat, das mag nur er selbst wissen - das enspricht nämlich
direkt

"0b01<<REFS0"

bzw.

"1 << REFS0"

da "0 << egalwas" immer 0 ist. Und "wasauchimmer | 0" bleibt
"wasauchimmer".

Sieht allerdings ungemein beeindruckend aus.

Warum nicht in der betreffenden Headerdatei statt Bit_nummern_
Bit_werte_ definiert werden können, wie es anderswo üblich ist, habe
ich bislang nicht nachvollziehen können.
Vielleicht kann mir ja jemand mal ein Argument nennen, das das
erklärt.

Ein Konstrukt, das nach der Bitnummernschreibweise so geschrieben würde
(C-Syntax):

  #define BIT1 1
  #define BIT2 2

  wert = (1 << BIT2) | (1 << BIT1);


sähe "bei mir" so aus:

  #define BIT1 0x2
  #define BIT2 0x4

  wert = BIT1 | BIT2;

von Peter D. (peda)


Lesenswert?

"Vielleicht kann mir ja jemand mal ein Argument nennen, das das
erklärt."


Lies Dir mal ein x-beliebiges *def.inc durch, da ist das am Anfang
erklärt.

Es gibt beim AVR nämlich Befehle, die mit der Bitnummer arbeiten (0..7)
und manche aber mit dem Wert (0x01..0x80).

Und damit man Symbole für beides verwenden kann, wird immer die
Bitnummer definiert.

Ein 0x80 in eine 7 umzuwandeln ist nämlich nicht so einfach.

Und für C wurde das dann einfach so übernommen.


0b00000 zu schreiben ist aber in der Tat Schwachsinn, entweder 0 oder
den Ausdruck ganz weglassen.


Peter

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter, danke für die Aufklärung:

  "Es gibt beim AVR nämlich Befehle, die mit der Bitnummer
  arbeiten (0..7) und manche aber mit dem Wert (0x01..0x80)."

Das ist in der Tat ein Argument.
Ich muss gestehen, den AVR nie in Assembler programmiert zu haben; und
die Prozessoren, bei denen ich das gemacht habe, wiesen diese
Besonderheit nicht auf, da sie - von einer Ausnahme abgesehen, auch
nicht über die Fähigkeit der Bitadressierbarkeit verfügten, wo das ja
wohl nötig ist. Waren halt weitestgehend keine µC.

(Beim MCS51 ist's einfach zu lange her, als daß ich mich um die
Uhrzeit noch daran erinnern könnte, muss aber wohl auch so sein)

von Peter D. (peda)


Lesenswert?

Ja, beim 8051 ist das auch so, z.B.:

setb 080h
..
setb 087h

setzen die Bits 0 .. 7 des Registers 080h

orl 080h, #001h
..
orl 080h, #080h

machen genau das gleiche, sind aber ein Byte und ein Zyklus länger,
gehen dafür auch für die Adresse 081h. Bitbefehle gehen nur für die
Register 080h, 088h, 090h usw.


Peter

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.