Forum: Mikrocontroller und Digitale Elektronik 2 Komplement Umrechnung


von verwirrter Mensch (Gast)


Lesenswert?

Hallo zusammen,
ich habe hier ein kleine Problem beim Programmieren und hoffe ihr könnt 
mir auf die Sprünge helfen. Ich lese ein 10 Bit Sensorsignal aus, dass 
aus 8 MSBs (c[1]) und aus 2 LSB (c[0]) besteht. Die 2 LSB sind 
linksbündig.
Mein Code sieht so aus:
1
unsigned long a
2
signed short b
3
a = ((unsigned long)c[1]<<2) + ((unsigned long)c[0]>>6);
4
if((a&0b0000001000000000)>0)
5
{
6
b = (signed short)(a&0x01FF)-512;
7
}
8
else
9
{
10
b = (signed short)a;
11
}

Was mich nun verwirrt ist, dass b nie größer als 255 oder kleiner als 
-256 wird. Aber es müsste doch eigentlich zwischen 511 und -512 liegen. 
Wo ist denn hier mein Denkfehler?

von Stefan++ (Gast)


Lesenswert?

Hallo,

du solltest jetzt nur noch erzählen welche Maschine du verwendest damit 
wir abschätzen können wie lang ein "long", "int" und "short" ist.
Ohne das gehts nicht !!!

von verwirrter Mensch (Gast)


Lesenswert?

Achso, sorry. Ich verwende HI-TECH COMPILER.
long hat also 32 und short 16 Bit.
Die long Variable ist hierfür zwar übertrieben, aber das hat schon 
seinen Grund. Die I²C Funktion muss teilweise auch 32 lange Variablen 
zurückgeben, daher die Länge.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dein Code ist korrekt, wenn auch etwas umständlich. Vielleicht liegt der
Fehler in der Ausgabe des Ergebnisses.

Falls das Ganze auf einem 8-Bit-Controller laufen soll, solltest du auf
die long-Arithmetik verzichten, da sie hier gar nicht benötigt wird. Ein
paar weitere Dingen lassen sich optimieren, bspw. kannst du

die Zeile
1
    b = (signed short)(a&0x01FF)-512;

ersetzen durch
1
    b = (signed short)a-1024;

Falls dein Controller zufälligerweise ein AVR sein sollte, würde ich den
ADC so konfigurieren, dass das Ergebnis nicht left-adjustiert wird
(ADLAR=0). Dann sparst du dir die Shifterei.

von Yalu X. (yalu) (Moderator)


Lesenswert?

verwirrter Mensch schrieb:
> Die I²C Funktion muss teilweise auch 32 lange Variablen
> zurückgeben, daher die Länge.

Das klingt nicht logisch: Die 32-Bit-Variable a verwendest du nur für
das Zwischenergebnis, das Endergebnis b, das wahrscheinlich übertragen
werden soll, hat nur 16 Bit. Ich würde alles mit maximal 16 Bit rechnen
bis zu dem Punkt, wo das Ergebnis per I²C ausgegeben werden soll. Dort
genügt dann ein einfacher Cast.

von Falk B. (falk)


Lesenswert?

@  verwirrter Mensch (Gast)

>mir auf die Sprünge helfen. Ich lese ein 10 Bit Sensorsignal aus, dass
>aus 8 MSBs (c[1]) und aus 2 LSB (c[0]) besteht. Die 2 LSB sind
>linksbündig.

Schön, aber was soll das Ergebnis sein? Ein 10 Bit Wert in einer 16 Bit 
Variablen? Siehe Bitmanipulation.

>unsigned long a
>signed short b

Jaja, der ewige Unsinn von C, dass keine Sau weiß, was ein long nun 
wirklich ist.

>a = ((unsigned long)c[1]<<2) + ((unsigned long)c[0]>>6);

Im Prinzip richtig, es fehlen aber Klammern.

>if((a&0b0000001000000000)>0)

Was mal sehr wirr ist, ein paar Leerzeichen wirken Wunder. 
Vorzeichenerweiterung geht einfacher, einfach die beren, leeren MSB mit 
dem aktuellen MSB aufüllen.
1
unsigned long a
2
signed short b
3
a = (((unsigned long)c[1])<<2) + (((unsigned long)c[0])>>6);
4
if(a & 0x200)
5
{
6
  b = (signed short)(a | ~0x3FF);
7
}
8
else
9
{
10
  b = (signed short)a;
11
}

von verwirrter Mensch (Gast)


Lesenswert?

Danke für die Antworten. Die Ausgabe erfolgt nur über eine LED mit 
if-Abfrage, ob der Wert größer als 260 ist.

Die Optimierungen werden sofort übernommen. :)
Das long ist wegen meiner I²C Auslese Funktion wirklich nötig. Der 
genaue Grund dafür wäre jetzt zu aufwendig zu erklären.

Ich benutze einen 8 Bit PIC Controller und der Messwert stammt von einem 
BMA250 (Beschleunigungssensor), der über I²C kommuniziert.

AHHHH.... Jetzt wo ich von dem Sensor erzähle fällt mir der Fehler 
selbst auf. Das konntet Ihr natürlich nicht wissen. Der Sensor ist auf 
2g range gestellt. Das bedeutet, die Erdbeschleunigung (1g) erzeugt 
natürlich nur die Hälfte des maximalen Wertes... -.-

Nochmal vielen dank für die Vereinfachungen. Da fällt einem erstmal auf, 
wie viel man noch lernen kann...

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.