Forum: Mikrocontroller und Digitale Elektronik aus 8Bit einen 10Bit Wert machen


von Marcel K. (viewer)


Lesenswert?

Hallo liebes Forum,

ich hänge an einer Stelle. Ich dacht es sei ganz einfach aber irgendwie 
bekomme ich es nicht hin.

Ich möchte aus einer 8Bit Zahl eine 10Bit Zahl machen.

Also aus 0xFF soll 0x3FF werden. Natürlich dachte ich einfach nur das 
ganze zweimal nach links schieben aber die "reingeschobenen" Zahlen sind 
Nullen.

Also (0xFF << 2) ergibt 0x3FC. Die Bits 0 und 1 sind "0"

Weiß von Euch jemand wie man das macht.

Ich möchte natürlich nicht nur 0xFF convertieren. Es sollen alle Werte 
zwischen 0-255 sein.

Hat jemand eine Idee?

Grüße,
Marcel

von WehOhWeh (Gast)


Lesenswert?

Das wird schwierig, weil informationen fehlen.

Dein Beispiel:

0xFF kann jetzt 0x3FF, 0x3FE, 0x3FD, 0x3FC sein.
Wie möchtest du entscheiden, was davon richtig ist?

Der Ansatz mit dem Schieben ist schon ok so.

Außer du hast mehrere Werte, dann kannst du interpolieren.

von Georg (Gast)


Lesenswert?

Entweder du hängst vorne oder hinten zwei Bits an, eine andere 
Möglichkeit hast du nicht. Hängst du sie vor die MSB, kannst du entweder 
Einsen oder Nullen anhängen. Einsen verschieben dir deinen Wert um 
0x3FF, Nullen machen nichts. Verschiebst du deinen Wert um zwei Bit, 
musst du ja die zwei Bits erfinden. Egal wie du Bit 0 und Bit 1 wählst, 
die beiden sind geraten. Man kann keine höhere Auflösung durch Zauberei 
herstellen.

von Karl H. (kbuchegg)


Lesenswert?

Marcel K. schrieb:
> Hallo liebes Forum,
>
> ich hänge an einer Stelle. Ich dacht es sei ganz einfach aber irgendwie
> bekomme ich es nicht hin.
>
> Ich möchte aus einer 8Bit Zahl eine 10Bit Zahl machen.
>
> Also aus 0xFF soll 0x3FF werden.

Warum?

Ich meine: Woran machst du fest, dass die unten 'reingeschobenen' Bits 1 
sein sollen?

von spess53 (Gast)


Lesenswert?

Hi

>Also (0xFF << 2) ergibt 0x3FC. Die Bits 0 und 1 sind "0"

>Weiß von Euch jemand wie man das macht.

Es könnte also deiner Meinung nach 0c3FC, 0x3FD, 0x3FE oder 0x3FF sein. 
Wie entscheidest du, was davon richtig ist?

MfG Spess

von Marcel K. (viewer)


Lesenswert?

Ja, wenn ich jetzt genauer darüber nachdenke.....


Ich hätte halt bei einem 8Bit 0xFF Wert, 0x3FF im 10 Bit PWM stehen.

Es ist aber eigentlich egal. Ob jetzt 0x3FF oder 0x3FC im Timer steht.

Danke für die schnelle Antworten und noch eine schöne Nacht,

Marcel

von Possetitjel (Gast)


Lesenswert?

Karl Heinz schrieb:

>>
>> Also aus 0xFF soll 0x3FF werden.
>
> Warum?
>
> Ich meine: Woran machst du fest, dass die unten
> 'reingeschobenen' Bits 1 sein sollen?

An den obersten beiden Bit der 8bit-Zahl?

von Amateur (Gast)


Lesenswert?

>0xFF soll 0x3FF

Aus 255 soll 1023 werden! Eine tolle Aufgabe!

von M. K. (sylaina)


Lesenswert?

Marcel K. schrieb:
> Ja, wenn ich jetzt genauer darüber nachdenke.....
>
>
> Ich hätte halt bei einem 8Bit 0xFF Wert, 0x3FF im 10 Bit PWM stehen.
>
> Es ist aber eigentlich egal. Ob jetzt 0x3FF oder 0x3FC im Timer steht.

0xFF != 0x3FF

Wie kommst du auf diese Idee?

von Marcel K. (viewer)


Lesenswert?

Na wenn ich mit einem 8Bit Wert 0x00 - 0xFF einen 10Bit PWM- Timer im 
"inverse-Mode" auch die 0x3FF erreichen kann. Wenn man jetzt 0xFF auf 
die 10Bit schiebt dann fehlt halt 0x03. Das ist aber OK für mich und hat 
sich geklärt.

0xFF = 100% "AN" bei 8 Bit, bei 10 Bit halt nur 99,7% "AN"

Grüße

von Phantomix (nichteingeloggt) (Gast)


Lesenswert?

(variable << 2) | (variable & 0x01 ? 0x03 : 0x00)

dupliziert das unterste Bit einfach
somit bleibt 0 0 und FF wird zu 3FF

von Markus (Gast)


Lesenswert?

Hi,

Marcel K. schrieb:
> Ich möchte aus einer 8Bit Zahl eine 10Bit Zahl machen.
>
> Also aus 0xFF soll 0x3FF werden.
1
uint8_t x8 = ...;
2
uint16_t x10 = x8 / 255.0 * 1023.0

Grüße, Markus

von J. T. (chaoskind)


Lesenswert?

Marcel K. schrieb:
> 0xFF = 100% "AN" bei 8 Bit, bei 10 Bit halt nur 99,7% "AN"

0xFF = 255

bei 8bit: 255/2^8-1 = 255/255 = 1 = 100%

bei 10bit: 255/2^10-1 = 255/1023 = 0,249irgendwas = 25%

von Thomas E. (thomase)


Lesenswert?

Markus schrieb:
> uint8_t x8 = ...;
> uint16_t x10 = x8 / 255.0 * 1023.0

Aber Floating Point muss man sich nicht aufhalsen.

x10 = (int)(x8 * 1023L / 255);

mfg.

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

Marcel K. schrieb:

> Na wenn ich mit einem 8Bit Wert 0x00 - 0xFF einen 10Bit PWM-
> Timer im "inverse-Mode" auch die 0x3FF erreichen kann. Wenn
> man jetzt 0xFF auf die 10Bit schiebt dann fehlt halt 0x03.

Was genau gefällt Dir an der Idee nicht, die obersten
beiden Bit in die untersten beiden einzukopieren? Das
erfordert einen - allerhöchstens zwei - zusätzliche
Assemblerbefehl(e).

von c-hater (Gast)


Lesenswert?

Possetitjel schrieb:

> Was genau gefällt Dir an der Idee nicht, die obersten
> beiden Bit in die untersten beiden einzukopieren?

Ja, das ist eine gute Frage, denn die Idee ist wirklich gut.

Sie sorgt dafür, daß Minimum und Maximum des 8Bit-Zahlenbereichs auf 
Minimum und Maximum des 10Bit-Bereiches gemapped werden und verteilt 
gleichzeitig den dadurch entstehenden Abbildungsfehler so gleichmäßig 
wie möglich über den Gesamtbereich.

Und das mit geringstem Rechenaufwand. Es ist wirklich nur ein einziger 
zusätzlicher Takt nötig.

Es wäre geradezu sträflich dumm, NICHT diesen Weg zu verwenden.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> und verteilt gleichzeitig den dadurch entstehenden Abbildungsfehler so
> gleichmäßig
Einziger Nachteil: sie macht einen großen Sprung in der Mitte. Bis 
dorthin wird immmer abgerundet, ab dort immmer "aufgerundet":
1
8 -> MSB|MSB -> 10 Bit -> Abstand zum Vorgänger
2
0    00         0         
3
1    00         4         4
4
2    00         8         4
5
3    00         12        4
6
4    00         16        4
7
:
8
126  11         504       4
9
127  11         508       4
10
128  11         515       7 ---  !
11
129  11         219       4
12
129  11         223       4
13
:
14
:
Man könnte aber auch das vorletzte Bit als LSB mit einfließen lassen, 
dann werden aus einen einzigen Sprung drei besser verteilte Sprünge:
1
8 -> MSB   -> 10 Bit -> Abstand
2
0    00    0         
3
1    00    4         4
4
2    00    8         4
5
3    00    12        4
6
4    00    16        4
7
:
8
62   00    248       4
9
63   00    252       4
10
64   01    257       5 --
11
65   01    261       4
12
:
13
126  01    505       4
14
127  01    509       4
15
128  10    514       5 --
16
129  10    218       4
17
130  10    222       4
18
:
19
190  10    762       4
20
191  10    766       4 
21
192  11    771       5 --
22
193  11    775       4
23
194  11    779       4
24
:
Also mein Vorschlag:
1
  wert = wert<<2 + wert>>6;

: Bearbeitet durch Moderator
von Possetitjel (Gast)


Lesenswert?

Lothar Miller schrieb:

> Man könnte aber auch das vorletzte Bit als LSB mit
> einfließen lassen, [...]

Meine Güte.

Ich zitiere: "Was genau gefällt Dir an der Idee nicht,
die obersten beiden Bit in die untersten beiden
einzukopieren?"

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wenn man aus einer 8-Bit-Zahl eine 10-Bit-Zahl machen will, dann 
multipliziert man sie mit 2x2 = 4 oder man schiebt sie einfach um 2 Bit 
nach links.

Über die untersten beiden Bits kann keine Aussage gemacht werden. Man 
kann bei dieser simplen Transformation schließlich nicht mehr 
Informationen erfinden als da sind! Irgendwelche Informationen in den 
beiden LSB hinzuzuphantasieren ist einfach falsch und Unsinn.

Also: Schieben um zwei Bits nach links und fertig. Die Auflösung bzw. 
der Informationsgehalt bleibt bei dieser Transformation dieselbe. Sie 
kann nicht besser bzw. gehaltvoller werden.

: Bearbeitet durch Moderator
von Possetitjel (Gast)


Lesenswert?

Frank M. schrieb:

> Wenn man aus einer 8-Bit-Zahl eine 10-Bit-Zahl machen will,
> dann multipliziert man sie mit 2x2 = 4 oder man schiebt sie
> einfach um 2 Bit nach links.

Das legst Du nicht fest. Wenn ich die 8bit-Zahl mit 4.011
multiplizieren will, dann tue ich das! Ehrlich! Es mag Dich
auf das Äußerste empören - aber das ist nicht verboten!

von operator (Gast)


Lesenswert?

Frank M. schrieb:
> Die Auflösung bzw.
> der Informationsgehalt bleibt bei dieser Transformation dieselbe. Sie
> kann nicht besser bzw. gehaltvoller werden.

Doch kann sie und das wurde oben auch schon gezeigt.
Bei einer reinen linksschieberei handelt man sich automatisch einen 
offset ein, während beim behandeln der unteren beiden Bits die Skala von 
10 bit besser ausgenutzt wird.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

operator schrieb:
> Doch kann sie und das wurde oben auch schon gezeigt.
> Bei einer reinen linksschieberei handelt man sich automatisch einen
> offset ein, während beim behandeln der unteren beiden Bits die Skala von
> 10 bit besser ausgenutzt wird.

Das klingt auf den ersten Blick zwar plausibel. Ich dachte auch zuerst, 
dass ich abwechselnd 01 und 10 in die beiden LSB schreiben würde, um 
einen besseren mittleren Wert zu bekommen.

Aber auf den zweiten Blick empfand ich das als Irrtum, nämlich aus 
folgendem Grunde:

Nehmen wir an, wir hätten einen 10-Bit-ADC. Wir lesen die Werte aus und 
können - aus welchen Gründen auch immer - sie nur als 8-Bit-Werte 
speichern.

Wir werden dann bestimmt NICHT immer abrunden, wenn wir die Daten in 8 
Bit quetschen wollen, also bestimmt KEINE Division durch 4. Wir werden 
das natürlich so machen:

    LSB   10->8 Bit
    ===============
    00   abrunden
    01   abrunden
    10   aufrunden
    11   aufrunden

Das heisst: Die 8 Bit-Werte sind bereits teilweise aufgerundet! Wenn Du 
jetzt bei der Rücktransformation von 8 nach 10 Bit wieder irgendwelche 
LSB dazuaddierst, würde NOCHMALS auf die aufgerundeten Werte aufaddiert 
werden.

Den von Dir angesprochenen Offset bekommst Du dann, wenn Du die LSB mit 
irgendwelchen Phantasien füllst. Die Werte sind dann nämlich 
systematisch zu hoch.

Und genau das ist absoluter Unsinn. Deshalb darf nur mit 4 
multipliziert bzw. um 2 Bits geschoben und KEINE LSB dazuerfunden 
werden. Alles andere ist falsch!

: Bearbeitet durch Moderator
von StefG (Gast)


Lesenswert?

Wenn die 8 bit Werte z.B. von einem ADC kommen, könnte man auch immer 4 
Messwerte addieren.
Dann hat man auch im LSB etwas, Stichwort Oversampling...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

StefG schrieb:
> Wenn die 8 bit Werte z.B. von einem ADC kommen, könnte man auch immer 4
> Messwerte addieren.
> Dann hat man auch im LSB etwas, Stichwort Oversampling...

Du bekommst vom ADC bereits gerundete Werte. 50% davon sind bereits 
aufgerundet. Wenn Du da noch weitere LSB draufaddierst, hast Du falsche 
Zahlen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Possetitjel schrieb:
> Ich zitiere: "Was genau gefällt Dir an der Idee nicht, die obersten
> beiden Bit in die untersten beiden einzukopieren?"
Ach schlags kaputt, Leseschwäche... :-o

von Boston (Gast)


Lesenswert?

Das kommt wohl auf den konkreten Fall ab.

Will ich einen Wertebereich ausnutzen, z.B. PWM von 0-100% dann ist 
reines Shiften eher unklug, da ich meine 100% dadurch nicht mehr 
erreiche.

Will ich mit dem Wert weiterrechnen, z.B. eine Addition/Subtraktion mit 
einem hochauflösendem Wert (Festkommaarithmetik) dann ist es wohl Jacke 
wie Hose, was ich in den beiden Bits reinschreibe, denn sie sind eh 
erfunden. Dann kann ich genausogut einfach nur shiften.

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> LSB   10->8 Bit
>     ===============
>     00   abrunden
>     01   abrunden
>     10   aufrunden
>     11   aufrunden

Und auf was rundest du 1111111111 auf?

von (prx) A. K. (prx)


Lesenswert?

Die Aufgabenstellung definiert die Lösung.

Wenn man den gesamten Bereich einer PWM abbilden will, dann sind 
Sprungstellen evtl. weniger wichtig als die Möglichkeit, an beiden Enden 
an den Anschlag gehen zu können. Wobei zu bedenken wäre, dass eine 
10-Bit PWM eigentlich nicht 1024 sondern 1025 Stufen umfasst, wenn "ganz 
ein" und "ganz aus" mit von der Partie sind.

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

Lothar Miller schrieb:

> Possetitjel schrieb:
>> Ich zitiere: "Was genau gefällt Dir an der Idee nicht, die
>> obersten beiden Bit in die untersten beiden einzukopieren?"

> Ach schlags kaputt, Leseschwäche... :-o

Okay, akzeptiert.

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.