Forum: Compiler & IDEs 2 Bytes zusammenfassen/ rechtsschieben


von T. C. (tripplex)


Angehängte Dateien:

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.

von Hc Z. (mizch)


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.

von Hans (Gast)


Lesenswert?

Hi,

sollte so gehen:
1
   uint16 result;
2
3
   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
1
  byte1 << 6
oder muß ich per casting operation byte1 als 16 bit Wert interpretieren 
lassen?
1
  (uint16)byte1 << 6
Bin mir da nie so sicher. Und habe gerade keine Umgebung da um das mal 
zu testen.

Grüße!

von Karl H. (kbuchegg)


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)

von T. C. (tripplex)


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.

von Flo (Gast)


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);

von Stumpf (Gast)


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

von Karl H. (kbuchegg)


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.

von Tom M. (tomm) Benutzerseite


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

von Sven H. (dsb_sven)


Lesenswert?

Sollte man nicht aufpassen dass bei

byte2 << 8

nicht aus dem byte "rausgeschoben" wird?

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

von Hc Z. (mizch)


Lesenswert?

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

Nein.  Warum, wurde bereits erläutert.

von T. C. (tripplex)


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)

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.