Hallo, ich bekomme von einem Sensor ein 10bit signed Wert, gespeichert in 2 Bytes, wobei das eine Byte die oberen 8 Bit darstellt und das andere Byte die 2 niederwertigsten Bit enthält zusätzlich sind in diesem Byte noch Flags. Ich habe nun durch ausblenden und verschieben die 10Bit signed in einer 16bit signed Integer-Variablen abgelegt. Nun meine Frage reicht es, wenn das 10. Bit gesetzt ist (Vorzeichen-Bit) dass ich die führenden Bits zu Einsen mache? So dass z.b. aus 10Bit signed: xxxx xx10 0000 0000 16Bit signed: 1111 1110 0000 0000 werden.
Bei der Zweier-Komplement-Darstellung haben negative Zahlen immer führende Einsen.
Das wäre die Methode um einen 10-Bit-Wert 'right-aligned' in einen 16-Bit-Wert unterzubringen. In Hinsicht auf mögliche spätere Erweiterungen (ein Sensor mit mehr als 10 Bit) würde ich eher dazu tendieren, den 10-Bit-Wert 'left-aligned' in den 16-Bit-Wert zu packen. Dazu müsstest Du dann einfach die 10 Bits um 6 Bits nach links schieben. Damit würden Dir sämtliche Anpassungsarbeiten erspart bleiben (abgesehen davon die Anzahl der Shifts zu ändern), falls mal ein Sensor mit höherer Auflösung zum Einsatz kommen könnte - Du arbeitest damit also immer mit 'echten' 16-Bit-Werten, egal ob der Sensor tatsächlich diese Auflösung beherrscht oder nicht. Anmerkung: Von rechts reingeschoben werden dann übrigens Nullen.
@Raimund: Dann funktionieren aber die ganzen Operationen (Addition, Subtraktion, usw.)aus der AVR-Libc nicht mehr, die müsste ich dann alle speziell für diese Darstellung neu schreiben, oder verstehe ich dich da nicht richtig?
>Dann funktionieren aber die ganzen Operationen (Addition, Subtraktion, >usw.)aus der AVR-Libc nicht mehr Wie kommst Du darauf?
16-Bit-Arithmetik bleibt 16-Bit-Arithmetik! Egal ob die Werte darin nun 'left-' oder 'right-aligned' sind! Bei 'right-aligned' muß man lediglich den Wert vorzeichenrichtig erweitern. Der Vorteil von 'left-aligned' ist, daß alle (weiterführenden) Berechnungen unangetastet bleiben können. Der Wertebereich der 16-Bit-Zahlen geht immer (vorzeichenbehaftet) von -32768 über 0 bis +32767. Wenn, wie von mir angedeutet, Deine 10-Bit-Werte um sechs Bits nach links verschoben werden und die unteren 6 Bits damit stets Null sind, so wird der 16-Bit Wertebereich auch hier komplet überstrichen - aber nun in Intervallen von 64 - also von -32768, -32704, -32640, ..., 32576, 32640 bis hin zu 32704. Oder mal anders erklärt: Dein 10-Bit-Wertebereich geht von -512 über 0 bis +511. Bei allen folgenden Berechnungen gehst Du ja dann von diesem Wertebereich aus. Nun kommt aber (dem Fortschritt sei dank) ein besserer Sensor mit einer höheren Auflösung, sagen wir z.B. 12 Bit, zum Einsatz. Nun geht der Wertebereich aber dummerweise von -2048 bis +2047. Jetzt stimmen also sämtliche weiterführende Berechnungen nicht mehr, da sich die Auflösung vervierfacht hat - die weiterführenden Berechnungen müssen also folglich (alle) angepaßt werden. Wären die Werte 'left-aligned' gewesen, bräuchte an den Berechnungen absolut nichts geändert werden. Ein simples links-Schieben für's 'left-aligned' ist außerdem noch wesentlich einfacher als ein vorzeichenrichtiges Erweitern bei 'right-aligned'. Warum also sollte man sich das Leben (in diesem Fall Programmieren) unnötig schwer machen?
Und wenn es dann mal den noch besseren Sensor mit 18 bit Auflösung gibt, was dann? Oliver
>Und wenn es dann mal den noch besseren Sensor mit 18 bit Auflösung gibt, >was dann? Dann schmeißt man die letzen beiden Bits weg, da diese sowieso nichts zur Genauigkeit beitragen, oder man erweitert gleich alle Meßwerte auf 32 Bit. Oder noch besser - auch wenn das Geschreie gleich wieder losgeht - nimmt man einfach den Datentyp float.
Jau, gutes Argument Oliver, aber ich sehe das genauso wie 'Gast'. Ich arbeite selbst in einer Firma, die intelligente Regel-, Steuer- und Messelektronik herstellt und kenne daher das 'Geschrei' der Kunden nach immer besser werdender Auflösung, Geschwindigkeit, usw. Dumm nur, daß in industriellen Umgebungen soviel verseuchende Komponenten existieren, die die Messsignale derart 'versauen', daß an eine präzise Messung mit utopischen Auflösungen (manchmal sogar schon größer 12-Bit) völlig illusorisch ist. Aber versuch das mal den Kunden klar zu machen.
@Raimund: Danke für die ausführliche Erklärung, allerdings hat die Sache mit dem "left-aligned" einen Haken, sobald ich multipliziere, bekomme ich in diesem Fall schneller einen Überlauf. Außerdem muss ich, wenn ich die Daten dann (dezimal lesbar) ausgeben will (seriell) auch wieder um 6 Bit nach links schieben, d.h. ich muss im Falle einer Auflösungserweiterung auch hier wieder meinen Code anpassen, das ist auch nicht optimal, da so etwas leicht vergessen wird. Zitat: "Nun geht der Wertebereich aber dummerweise von -2048 bis +2047. Jetzt stimmen also sämtliche weiterführende Berechnungen nicht mehr, da sich die Auflösung vervierfacht hat - die weiterführenden Berechnungen müssen also folglich (alle) angepaßt werden." Dem kann ich so nicht zu stimmen oder ich sehe das Problem noch nicht. Wenn ich 10Bit (oder 12Bit) in einer Integer-Variablen richtig ablege, dann haben folgende Berechnungen mit der Variablen keinen Einfluss, außer evtl. Überläufe, aber das Problem habe ich mit "left-aligned" auch siehe oben.
Thomas schrieb: > @Raimund: > Danke für die ausführliche Erklärung, allerdings hat die Sache mit dem > "left-aligned" einen Haken, sobald ich multipliziere, bekomme ich in > diesem Fall schneller einen Überlauf. Das schon, aber einen Überlauf mußt Du so oder so einplanen und dann entsprechend weiterverarbeiten. Bei 16-Bit x 16-Bit kommt (eigentlich) immer ein 32-Bit-Wert bei raus, kann also Deine Argumentation hier nicht unterstützen. > Außerdem muss ich, wenn ich die Daten dann (dezimal lesbar) ausgeben > will (seriell) auch wieder um 6 Bit nach links schieben, d.h. ich muss > im Falle einer Auflösungserweiterung auch hier wieder meinen Code > anpassen, das ist auch nicht optimal, da so etwas leicht vergessen wird. Häh, dies kann ich nun nicht nachvollziehen. Wenn Du mit "dezimal lesbar" eine Konvertierung in BCD meinst, ist der 'Mehraufwand' nur zwei Dezimalstellen oder ein lächerliches Byte. Warum sollte man hier etwas um 6 Bits nach links schieben wollen? > Zitat: "Nun geht der Wertebereich aber dummerweise von -2048 bis +2047. > Jetzt stimmen also sämtliche weiterführende Berechnungen nicht mehr, da > sich die Auflösung vervierfacht hat - die weiterführenden Berechnungen > müssen also folglich (alle) angepaßt werden." > > Dem kann ich so nicht zu stimmen oder ich sehe das Problem noch nicht. > > Wenn ich 10Bit (oder 12Bit) in einer Integer-Variablen richtig ablege, Ein 'richtig' gibt es nicht immer. Ein 'praktischer' oder 'geschickter' ist aber, vmtl. nicht nur meiner Meinung nach, die 'left-aligned'-Methode. > dann haben folgende Berechnungen mit der Variablen keinen Einfluss, > außer evtl. Überläufe, aber das Problem habe ich mit "left-aligned" auch > siehe oben. Uff, muß ich jetzt tatsächlich ein praktisches Beispiel bringen? Laß uns also mal annehmen der 10-Bit-Sensorwert käme von einem ADC. Laß uns weiter annehmen, das -512 einer Spannung von -1V entspräche und 511 einer Spannung von +0,998...V. Damit hätte ein Bit die Wertigkeit von etwa 2mV. Wenn man nun den ADC-Wert zur Anzeige auf einem Display in "Volt" umrechnen müßte, muß man wohl oder übel den Wert mit einer Konstanten (in diesem Fall: 0,001953125) multiplizieren. Nun kommt der Knackpunkt. Wenn die Werte, unabhängig von der Auflösung, immer 'left-aligned' wären, so wäre der Muliplikator stets 0,0000305...! Im Falle der Verwendung eines Sensors mit nun 12 Bit, würde sich der Multiplikator zu 0,000488... ändern. Diesen Multiplikator müßtest Du eben, nach Deiner 'right-aligned'-Methode, immer wieder an die Auflösung des Sensors anpassen. Das meinte ich damit, daß weiterführende Berechnungen bei der 'left-aligned'-Methode unangetastet bleiben (können). Jetzt alles klar? Resumée: Wenn Du Dir um spätere Erweiterungen (ein Sensor mit höherer Auflösung) nicht scheren mußt, dann vergiss das bisher gesagte, und schreib Dein Programm so wie Du es gewohnt bist - eben ganz speziell auf die eine einzige Anwendung orientiert, ohne der Einplanung von späteren Änderungen oder Erweiterungen. Für den Fall, das Du aber Code schreiben willst, den man evtl. auch später noch einmal verwenden will (das Rad muß man ja nicht ständig neu entwickeln), dann schreibt man ihn üblicherweise so, das er universell ist und z.B. mit (mehr oder weniger) 'genormten' Eingangsgrößen arbeiten kann. Jeder möge aber letztendlich seiner eigenen Philospophie folgen.
> Häh, dies kann ich nun nicht nachvollziehen. > Wenn Du mit "dezimal lesbar" eine Konvertierung in BCD meinst, ist der > 'Mehraufwand' nur zwei Dezimalstellen oder ein lächerliches Byte. > Warum sollte man hier etwas um 6 Bits nach links schieben wollen? In meinem Fall muss ich nur den Wert an der seriellen Schnittstelle ausgeben, dazu benutze ich die Funktion itoa(), diese gibt mir den Integer als String zurück den ich dann als "lesbare" Zahl an die serielle Schnittstelle gebe. Würde ich deine Methode benutzen müsste ich erst wieder 6 mal rechts schieben, damit das "left aligned" zu einem "right aligned" wird das die itoa()-Funktion richtig interpretiert. Würde ich das nicht machen müsste ich ein PC-Programm schreiben das mir die übertragenen Werte wieder in den "original" Zahlenbereich transformiert (rechts schieben). Damit müsste ich ein µC-Program und ein Programm für den PC schreiben. Was jetzt weniger Arbeit ist kannst du dir sicher denken. Danke trotzdem für die ausführliche Diskussion.
Thomas schrieb: >> Häh, dies kann ich nun nicht nachvollziehen. >> Wenn Du mit "dezimal lesbar" eine Konvertierung in BCD meinst, ist der >> 'Mehraufwand' nur zwei Dezimalstellen oder ein lächerliches Byte. >> Warum sollte man hier etwas um 6 Bits nach links schieben wollen? > > In meinem Fall muss ich nur den Wert an der seriellen Schnittstelle > ausgeben, dazu benutze ich die Funktion itoa(), diese gibt mir den > Integer als String zurück den ich dann als "lesbare" Zahl an die > serielle Schnittstelle gebe. Yip, kann man so machen. > Würde ich deine Methode benutzen müsste ich erst wieder 6 mal rechts > schieben, damit das "left aligned" zu einem "right aligned" wird das die > itoa()-Funktion richtig interpretiert. Ein rechtsschieben ist sicher nicht nötig. Es kommt lediglich ein anderer String bei raus. > Würde ich das nicht machen müsste ich ein PC-Programm schreiben das mir > die übertragenen Werte wieder in den "original" Zahlenbereich > transformiert (rechts schieben). Damit müsste ich ein µC-Program und ein > Programm für den PC schreiben. > Was jetzt weniger Arbeit ist kannst du dir sicher denken. Dazu kann ich nur folgendes sagen: Es ist immer eine Frage, wie ich meine String-Werte interpretiere. Bisher hast Du ja den übertragenen String als 10-Bit-Wert interpretiert. Wo ist jetzt das Problem ihn als 16-Bit-Wert zu interpretieren??? Es gibt hier nicht mehr oder weniger Arbeit. Wenn Du den Wert auf dem PC in z.B. SI-Einheiten anzeigen willst, mußt Du den String doch so oder so 'anfassen'. Das kann ja nun nicht das Problem sein!?! > Danke trotzdem für die ausführliche Diskussion. Gern geschehen.
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.