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
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;
"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
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)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.