mikrocontroller.net

Forum: Compiler & IDEs Verständnis Problem folgender code-Zeile


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Habe ein kleines Verständnisproblem mit folgenden code - es geht darum,
den 10 BIT Wert des ADC's eines AVR's in ein Register zu lesen.

uint16_t value;   //Sonnenklar
value = ADCL;     //Sonnenklar
value += ADCH<<8; //keine Ahnung

Was mir klar ist, ist selbstverständlich das "+=" - sowie auch das
Schieben um 8 BIT-Positionen nach Links. Aber wie kann das
Funktioneren. Es wird doch erst Addiert und zugewiesen und dann
geschoben - so dass die erste Zuweisung mit ADCL eigentlich verloren
ist.

Wie wird die Zeile übersetzt?
Ergebnis ist genau dass, was ich benötige - aber wieso?

Das Listing-File habe ich mir auch angesehen - hilft aber auch nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es wird doch erst Addiert und zugewiesen und dann
> geschoben

Nein. Es wird erst der Ausdruck rechts vom = ausgewertet.
Wie bei jeder normalen Zuweisung auch. Nur dass halt
bei einem += nicht einfach zugewiesen wird, sondern
aufaddiert. Das ist alles.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eben - es wird aufaddiert - das ist ja noch ok.

Aber - wie kommt ADCHigh auch wirklich in das Highbyte von value? ->
das wird ja über das schieben realisiert - und das verstehe ich nicht.

Autor: Fabian Scheler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist das Problem??? Beispiel:

uint_16 value = 0;

ADCL = 0xcd;
ADCH = 0xab;

value = ADCL;

/* value = 0xcd */

value += (ADCH << 8)

/* ADCH      = 0xab =>
   ADCH << 8 = 0xab00
   value(old)= 0x00cd
   value(new)= 0xabcd
*/

Alles klar?

Ciao, Fabian

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
value = value + ( ADCH << 8 );

ADCH wird um 8 Bit nach links geschoben und dann
zu value (welcher bereits 8 Bit von ADCL enthält)
addiert:

ADCL   1010 0011
ADCH   0000 0010

value = ADCL:
    0000 0000 1010 0011

ADCH << 8:
    0000 0010 0000 0000

value += ADCH << 8:
   beides addieren
    0000 0010 1010 0011
   und value zuweisen.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok - dann frage ich mich nun, wie kann ich in einer Variable, die nur
8-BIT breit ist einen Wert um 8-Bit nach links schieben? In Windows
nennt man sowas overflow!

Das folgendes so einfach gemacht wird ist mir wirklich suspekt - das
wusste ich nicht.

ADCH      = 0xab
ADCH << 8 = 0xab00

Danke euch beuden.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t

Rat mal, wofür die 16 steht!

Autor: Fabian Scheler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum einen hast du uns nicht verraten, welchen Typ 'ADCH' hat, das
könnte durchaus ein 16-Bit Typ sein (ich habe keine Ahnung was sich
dahinter nun wirklich verbirgt), außerdem kommt es natürlich darauf an,
was für ein Typ 'ADCH << 8' eigentlich ist und das hat was mit
'Integer Promotion' (oder?) zu tun. Wenn du folgendes machst

uint_16 value = 0;
value = (uint_8)(ADCH << 8);

dürfte value freilich immer der Wert '0' zugewiesen werden.

Ciao, Fabian

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Alex - kein Kommentar - dein Beitrag ist sinnlos!

@Fabian - bei ADCH handelt es sich um das High-Byte des Ergebnisses des
AD-Wandlers - ADCH ist defenetiv 8-BIT breit! Type uint_8!

Und nun nochmal - warum kann ich in einer 8-BIT Variable 8-BITS nach
links schieben und erhalte dann eine 16-BIT Variable?

Keine Ahnung!

Autor: Fabian Scheler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich in meiner Antwort doch eigentlich erklärt - was sich hinter
'Integer Promotion' bzw. 'impliziten Typumwandlungen' verbirgt,
kannst du über google oder K&R selbst herausfinden, das gehört dazu!

Ciao, Fabian

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Formal müßte man (uint_16)ADCH << 8 schreiben, d.h. vorher auf 16Bit
erweitern und schaden tuts ja nicht, macht es nur besser lesbar.


Aber der C Standart schreibt vor, daß Berechnungen so ausgeführt werden
müssen, daß das gleiche Ergebnis rauskommt, als wären sie mindestens
16bittig ausgeführt worden.

Deshalb kann man auch oft sehen, daß der AVR-GCC unnötig auf 16Bit
erweitert, obwohl alle Operanden 8bittig sind. Der AVR-GCC ist da
leider etwas optimierungsfaul.


Peter

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Der AVR-GCC ist da
> leider etwas optimierungsfaul.

Es hat ihm einfach nur niemand beigebracht.  Für die meisten
GCC-Architekturen ist das kein Thema, weil deren natürliche
Verarbeitungsbreite größer ist (32 bits) als die vom Standard
geforderten 16 bits.  Dadurch ist bei ihnen die Verarbeitung
von 8-Bit-Werten nicht schneller als die von 16- oder 32-bit-
Werten (oft eher noch langsamer).

Kommt hinzu, dass wohl die AVR-GCC-Implementierung insgesamt
eher vorgaukelt, eine 16-bit-Implementierung zu sein, d. h. die
internen Befehle (insns) sind in der Zwischensprache als
16-bit-Befehle organisiert, die dann jeweils in den Assemblercode
für eine 16-bit-Operation direkt auflösen.  Hier liegt sicher
Optimierungspotenzial, leider jedoch in einer Form, dass man
praktisch einen Großteil der existierenden Implementierung
neu anfangen müsste, wollte man das ändern.

Übrigens schreibt der Standard nicht "Promotion auf mindestens
16 bits" vor, sondern "Promotion auf int".  D. h. obige Rechnung
bewirkt zwischenzeitlich ein Ergebnis, das mit einem u. U.
fehlerhaften Vorzeichen behaftet sein könnte, welches anschließend
bei der Zuweisung auf uint16_t wieder vernichtet wird.  In
diesem speziellen Fall nur ,,könnte'', da ADCH nur einen
Wertebereich von 0 bis 3 hat, mithin immer positiv ist.  Aber
solche impliziten Vorzeichenmutation bergen eine Gefahr in
sich, siehe

http://www.mikrocontroller.net/forum/read-2-368138.html

An den OP:
value = ADCW;

hätte es übrigens auch getan. ;-)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg:

Danke für den Hinweis ADCW - wieder was dazu gelernt ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.