www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Auf ein Byte zugreifen


Autor: Oktoberfestbesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Ich sammle so meine ersten Programmiererfahrungen mit dem ATtiny25 und 
AVRStudio4.
es geht mir um die Frage, wie ich auf ein einzelnes der 4 Byte einer 
unsigned long int variable zugreifen kann.
unsigned long int my_ul32;
unsigned char my_byte;

my_byte = my_ul32;        // lies byte_0
my_byte = my_ul32 >> 8;   // lies byte_1
my_byte = my_ul32 >> 16;  // lies byte_2
my_byte = my_ul32 >> 24;  // lies byte_3

my_ul32 = (my_ul32 & 0xFFFFFF00) | my_byte;       // schreib an position 0
my_ul32 = (my_ul32 & 0xFFFF00FF) | my_byte << 8;  // schreib an position 1
my_ul32 = (my_ul32 & 0xFF00FFFF) | my_byte << 16; // schreib an position 2
my_ul32 = (my_ul32 & 0x00FFFFFF) | my_byte << 24; // schreib an position 3
Ich weiss jetzt nicht ob der GCC (AVRWIN) meine Absicht durchschaut und 
das obtimieren kann, oder ob der jetzt beigeht und tatsächlich 24 mal 
schieben läßt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oktoberfestbesucher schrieb:
> Hallo,
> Ich sammle so meine ersten Programmiererfahrungen mit dem ATtiny25 und
> AVRStudio4.
> es geht mir um die Frage, wie ich auf ein einzelnes der 4 Byte einer
> unsigned long int variable zugreifen kann.
> ...

Dazu gibt es mehrere Varianten (je nach persönlicher Vorliebe)
hier schon etliche Threads:
- Adresse der Variable in eine uint8_t* casten und darüber mit
  einem Index auf dei Byte zugreifen (mein Favorit)
- Mit einer union (Liebling der meisten anderen)
- Shiften so wie du es machst (portabel, aber ansonsten
  uneffizient und unschön m.E.)
- ...

> Ich weiss jetzt nicht ob der GCC (AVRWIN) meine Absicht durchschaut und
> das obtimieren kann, oder ob der jetzt beigeht und tatsächlich 24 mal
> schieben läßt.

Ich fürchte nein; genaueres sieht man am erzeugten Code.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich denke, eine Union wäre geschickter, meinst du nicht?
union {
unsigned long LongVar;
unsigned char ChArr[4];
} stLong;

Zugriff auf die einzelnen Bytes dann mit VarName.ChArr[x]. Keine Gewähr 
für den Code, nur beispielhaft ;)

Ralf

Autor: Oktoberfestbesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> - Adresse der Variable in eine uint8_t* casten und darüber mit
>   einem Index auf dei Byte zugreifen (mein Favorit)

kannst du mal einen Code-Schnipsel dazu posten,
ich kriegs nicht gecastet

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

Bewertung
0 lesenswert
nicht lesenswert
  uint32_t Value;
  uint8_t* pHelp;

  // mach was mit allen Bytes von Value
  pHelp = (uint8_t*) &Value;
  for( i = 0; i < sizeof( Value ); ++i )
    output( pHelp[i] );

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo, genau so meinte ich das.

(Danke, habe in der Zwischenzeit nett gegrillt und ein leckeres 
Rauchbier getrunken...)

Wobei es auch ohne Zeigervariable geht; nicht unbedingt besser oder 
übersichtlicher, aber geiziger:
  uint32_t Value;

  for( i = 0; i < sizeof( Value ); ++i )
    output( ((uint8_t*)&Value)[i] );

Autor: Oktoberfestbesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> output( pHelp[i] );

Danke für die Antwort.
Das man einem Pointer auch einen Index dranhängen kann, hab ich bisher 
nicht gewußt.
Muß ich testen! Besten Dank



und  Klaus Wachtler (mfgkw) schrieb:
> output( ((uint8_t*)&Value)[i] );

Danke für die Antwort, sieht gut aus. Ich versteh es noch nicht ganz 
100%,
werde es aber testen.
Frage dazu: wie würde denn umgekehrt input gehen?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem output hatte ich ja nur die Version von KHB aufgegriffen.

Original hast du ja direkte Zuweisungen.
Das würde etwa so aussehen:
    // eine Richtung:
    mybyte_mostsignificant = ((uint8_t*)&Value)[3];
    mybyte3                = ((uint8_t*)&Value)[2];
    mybyte2                = ((uint8_t*)&Value)[1];
    mybyteleastsignificant = ((uint8_t*)&Value)[0];

    // andere Richtung:
    ((uint8_t*)&Value)[3] = mybyte_mostsignificant;
    ((uint8_t*)&Value)[2] = mybyte3;
    ((uint8_t*)&Value)[1] = mybyte2;
    ((uint8_t*)&Value)[0] = mybyteleastsignificant;

"most" und least" bezieht sich auf einen Rechner mit Little 
Endian-Architektur, bei einem BE-System müsste man die Bytes andersrum 
interpretieren.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oktoberfestbesucher schrieb:
> Ich versteh es noch nicht ganz 100%,

&Value liefert dir die Adresse deiner Variable value (von der
ich ausgehen, daß sie 32 Bit groß ist).

(uint8_t*)&Value ist immer noch dieselbe Adresse, allerdings
zu interpretieren als Zeiger auf uint8_t, also Zeiger auf Byte.
Das könnte jetzt ein Zeiger auf ein Byte sein, oder auf das erste
eines ganzen Felds von Byte.
(Siehe C-Buch: Analogie zwischen Zeigern und Feldern...)

Mit ((uint8_t*)&Value)[0] etc. nimmt man jetzt das
soundsovielte Element des vermeintlichen Feldes, als das
soundsovielte Byte von Value.
Solange man im Bereich [0] bis [3] bleibt, greift man damit
auf die entsprechenden Byte von Value zu.

Autor: Oktoberfestbesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Solange man im Bereich [0] bis [3] bleibt, greift man damit
> auf die entsprechenden Byte von Value zu.

Sahneschnitten_toll!

Besten Dank!

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.