mikrocontroller.net

Forum: Compiler & IDEs 2 Bytes zusammenfassen/ rechtsschieben


Autor: T. C. (tripplex)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich bin von Assembler auf C, mit dem GCC Tutorial bin ich zwar weit
gekommen aber jetzt komme ich nicht mehr weiter.
Ein ADC ( ADS7822 ) liefert den µC 2 'zerstückelte' Bytes, welche
ich entsprechend aufbereiten möchte damit ich diese problemlos
weiterverwenden kann.

Meine Idee war es, die 2 Bytes ( 2* uint_t 8) welche ich empfange zu
einen uint_t 16 zusammenfassen und dann einfach 2 mal rechtsschiebe
wodurch ich meine gewünschten Bitpositionen erhalte.

Dadurch stellen sich mir 2 Fragen:

a) Wie fasst man 2 uint_t 8 Bytes zu einem uint_t 16 zusammen ?
b) Wie 'schiebt' man in C ?

Als Anhang ist eine kleine "Skizze" welche ich eingescannt habe welche
mein Problem beschildert.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lösungsskizze:  Du schiebst das obere Byte 6mal links, das untere Byte 
2mal rechts, und veroderst die beiden Ergebnisse.  Aber:
> b) Wie 'schiebt' man in C ?
Das herauszufinden überlasse ich nun wirklich Dir.  Denn ohne ein gutes 
Buch und ohne das so zu kennen, dass Du sowas sofort findest, bist Du 
sowieso verloren.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

sollte so gehen:
   uint16 result;

   result = (byte1 << 6) | (byte2 >> 2);

<< oder >> sind die Schiebeoperatoren in C´. Steht aber wirklich in 
jedem Buch.
Jetzt noch ne doofe Frage von mir:
reicht
  byte1 << 6
oder muß ich per casting operation byte1 als 16 bit Wert interpretieren 
lassen?
  (uint16)byte1 << 6
Bin mir da nie so sicher. Und habe gerade keine Umgebung da um das mal 
zu testen.

Grüße!

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

Bewertung
0 lesenswert
nicht lesenswert
Hans schrieb:

> Bin mir da nie so sicher.

Die Merkhilfe in C lautet:
Jede Operation wird immer minimal im Zahlenraum int gemacht. Kleiner als 
mit int wird nicht gerechnet.

Die einzige Ausnahme: Wenn der Optimizer beweisen kann, dass sich das 
Ergebnis nicht ändert, wenn er eine Operation in signed char (oder 
unsigned char) macht, dann darf er einen Gang zurückschalten. Für den 
Optimizer gilt (wie immer): Das Ergebnis darf sich nicht von dem 
unterscheiden, was man ohne Optimierung erhalten hätte. Er ist an die 
"As If" Regel gebunden.

D.h. auf einem AVR ist daher grundsätzlich jegliche Berechnung erst mal 
mindestens 16-Bit (es sei denn, Optimizer, eh schon wissen)

Autor: T. C. (tripplex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure Antworten.
Ich habe mich vertan, ich muss nur 1x schieben da ich auf
der "Skizze" das Datenbit 0 verschludert habe und falsch weiter
gedacht habe. Somit würde das doch viel einfach werden oder?

Folgende Überlegung:
Im Highbyte ein ROR - Das Datenbit DB7 was 'links' 'rausfallen' würde,
wird im Carry gespeichert.

Danach noch ein ROR mit dem Lowbyte und das Carry was im Highbyte
rausgefallen ist, wird nun im Lowbyte rausgeschoben ( als MSB),
das LSB im Lowbyte was ich nicht brauche verschwindet.

Dann müsste man den Compiler sagen das die neue uint_t 16 Variable
aus den 2 Alten Bytes besteht.

---

uint_t 16 ADC_In;

ADC_In = (byte1 >>1) | (byte2 >>1)

---

Woher wüsste der Compiler ob er ein ROR oder LSR benutzen soll?
Sorry für die blöde Frage aber ich bin ein C Anfänger.. .






Ich habe schon geahnt das die Antwort "Das steht doch in jeden C Buch
drin" kommt, aber ein besagtes C-Grundlagen Buch bekomme ich wenn
ich Glück habe Anfang nächsten Monats für eine Zeit lang ausgeliehen :)

Bis dahin wollte ich weiter die Firmware für meine Hardware schreiben,
da ich in den vergangenden Tagen die Sachen nur bei mir auf dem 
Schreibtischlagen und ich nichts angerührt habe. Wollte schauen wie weit 
ich komme.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pascal L. schrieb:
> uint_t 16 ADC_In;
>
> ADC_In = (byte1 >>1) | (byte2 >>1)

falsche Herangehensweise.

(Im Beispiel jetzt sind relevante bits auf 1 gesetzt, nichtrelevante auf 
0)

Oberes Byte                           Unteres Byte
  0001 1111                            1111 1110

jetzt erweitern wir beide in Gedanken auf 16 bit (von vorne)

Oben                                 Unten
  0000 0000 0001 1111               0000 0000 1111 1110

so und jetzt zählen wir die Verschiebungen:
                                       hier 1 nach rechts
                                    (0000 0000 0111 1111)
  also muss das Obere um 7 nach links,
  damit die relevante Bits aneinderpassen.
  (0000 1111 1000 0000)

jetzt das Ganze in einer Variable zueinander verodern (Variable war 
vorher 0), und schon liegt das Ergebnis vor:

uint16_t erg = (byte1 << 7) | (byte2 >> 1);

Autor: Stumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich benutze für soche zugriffe meist einen Union, macht es in meinen 
Augen schöner zu lesen.

Erzeuge Dir in deinem Header ein paar neue Typen.

das hier im header !

typedef struct
{
  UCHAR low;
  UCHAR high;
} _2uchar_t;


//------------

union uint_u
{
  unsigned int  ui;
  _2uchar_t     uc;
  signed int   _int;
};

//-----------

typedef union uint_u     uint_tu;

#define UINT_TU        uint_tu

// header ende !!!

dann kannst du leicht mit


UINT_TU meineNeueVariable;   --> erzegen

--> Daten speichern
meineNeueVariable.uc.low = byte1;
meineNeueVariable.uc.high = byte2;

-->und nun noch verschieben!
meineNeueVariable.ui = meineNeueVariable.ui >> 1;

So und schon sollten die daten in der Variable
meineNeueVariable.ui passen.


Viel Spaß

Stumpf

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

Bewertung
0 lesenswert
nicht lesenswert
Pascal L. schrieb:

> Folgende Überlegung:
> Im Highbyte ein ROR - Das Datenbit DB7 was 'links' 'rausfallen' würde,
> wird im Carry gespeichert.

Hier rächt sich deine Assembler Vergangenheit.
In C gibt es kein Carry.

Alles was du hast, sind Variablen und Operationen. Jede Operation wirkt 
auf die Variable und nur auf diese. Seiteneffekte in dem Sinne, die du 
mit dem Carry vor hast, gibt es nicht.

Das ist der Preis, den du zahlen musst, wenn du eine gewisse Abstraktion 
von der Hardware hast.

Autor: Tom M. (tomm) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pascal L. schrieb:
> Ich habe schon geahnt das die Antwort "Das steht doch in jeden C Buch
> drin" kommt, aber ein besagtes C-Grundlagen Buch bekomme ich wenn
> ich Glück habe Anfang nächsten Monats für eine Zeit lang ausgeliehen :)

Bis dahin kannst du ja hier etwas schmökern und dir einige Grundlagen 
erarbeiten:

http://de.wikibooks.org/wiki/C-Programmierung

Ich programmiere schon lange / immer wieder mal C und kann finde ein 
Buch sehr nützlich, auch wenn's mittlerweile auseinander fällt %) ... 
Das Standardwerk von K&R: ISBN 978-0131103627

Autor: Sven H. (dsb_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sollte man nicht aufpassen dass bei

byte2 << 8

nicht aus dem byte "rausgeschoben" wird?

Ich würde erst mal casten und dann schieben...

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Sollte man nicht aufpassen dass bei
> byte2 << 8
> nicht aus dem byte "rausgeschoben" wird?

Nein.  Warum, wurde bereits erläutert.

Autor: T. C. (tripplex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da ist man einmal nur kurz Mittag essen und dann gibt es schon eine
neue Antwort :)
Jetzt habe ich es wirklich verstanden.

Ich merke das ich ohne ein C Buch nicht weiter komme aber das werde
ich mir noch besorgen.

---

Ich kann euch von tollen Neuigkeiten berichten.
Es funktioniert! riesig-freu
Bei einer Spannug von 2.503V am ADS7822  spukt mir mein MCP4922
eine Spannung von 2.506V aus freut mich riesig =) .
Was mich am meisten auch noch freut ist das dass SPI Interface
mit 1Mhz läuft und keine Probleme macht.

Gibt doch nichts besseres als eine gut durchgeplante Hardware
auf der man sich verlassen kann wodurch man dann alle Fehler auf die
Software schieben kann. x)

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.