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.
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.
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!
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)
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.
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);
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
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.
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
Sollte man nicht aufpassen dass bei byte2 << 8 nicht aus dem byte "rausgeschoben" wird? Ich würde erst mal casten und dann schieben...
> Sollte man nicht aufpassen dass bei > byte2 << 8 > nicht aus dem byte "rausgeschoben" wird? Nein. Warum, wurde bereits erläutert.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.