mikrocontroller.net

Forum: Compiler & IDEs 2er Komplement und C


Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich habe mal wieder ein Problem. Diesesmal geht es um das 2er
Komplement. Ich möchte gerne, eine 2er Komplementzahl in eine
Dezimalzahl umwandeln aber ich weiß nicht wie ich das machen soll. Das
ganze soll im AVR-Studio geschehen und ein µC soll es mir nachher auf
dem Bildschirm ausgeben. Das 2er Komplement erhalte ich von einem
Beschleunigungssensor und ich würde diese Werte halt gerne Dezimal
ausgeben, so wie es unten kurz beschrieben ist:
Dez  Bin      Hex
+511  01 1111 1111  0x1FF
+510  01 1111 1110  0x1FE
   ...
  +1  00 0000 0001  0x001
   0  00 0000 0000  0x000
  -1  11 1111 1111  0x3FF
   ...
-511  10 0000 0001  0x201
-512  10 0000 0000  0x200

Könnte mir jemand einen Tip geben, wie ich das im GCC realisiere oder
mir sogar einen kleinen Beispielcode dazu geben? Ich komme einfach
nicht weiter.

Schonmal danke und Gruß,

Marian

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Liess die 10 Bit? von deinem Sensor ein (in ein 16bit int), teste ob das
10te gesetzt ist (=> negative Zahl) und setze dann bits 11-15 auf eins.

dann hast du einen 16bit int, der vorzeichenrichtig deinen Sensorwert
enthält.

/Ernst

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdlib.h>

uint16_t val;
char b[20];
...
val = ...;
itoa(val, b, 10);

Oder halt sprintf() benutzen, wenn du die nötigen Resourcen
dafür hast.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Könnte mir jemand einen Tip geben, wie ich das im GCC realisiere

sprintf.

Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal Danke an alle!
@Jörg: Leider funktioniert dein Vorschlag mit itoa nicht. Ich bekommen
immernoch Werte von 0 bis 1023 aber leider nicht die negativen die ich
haben möchte (also von -512 bis 511).

Hat noch jemand ne andere Idee oder muss ich an deinem Vorschlag nur
noch etwas ändern, denn was die 10 in itoa bedeutet weiß ich noch
nicht.
Leider kann ich sprintf nicht nutzen, weil ich wenig Ressourcen habe
und diese Funktion auch noch nicht ganz verstanden habe.

Gruß,
Marian

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst auf jeden Fall die Vorzeichenbits wie ich geschrieben habe
erweitern, sonst kann itoa, sprintf etc. garnicht wissen, dass es eine
negative zahl ist.

also
int16_t val;
val=read_from_sensor();
if (val & (1<<10)) {
  val |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<10);
}
...itoa(val...
...sprintf(...val...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der dritte Parameter im Aufruf von itoa ist die Basis für die
ausgegebene Zahl (also 10 -> dezimal). Wenn man eine 16 eingibt, ist
die Ausgabe hexadezimal usw...

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also 0..1023 -> -512..511

Wo ist das Problem ?


Y = X - 512;

fertich


Peter

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@peter:

das stimmt so nicht:

der chip sendet -512, als bits:
0000 0010 0000 0000

nach deiner umrechnung kommt da 0 raus, nicht -512...

Beim kopieren eines 2er-Komplement werts in eine variable mit mehr
bits, muss man immer das Vorzeichenbit auf die neu hinzugekommenen Bits
kopieren, also:

1o bit eingelesen:
0000 0010 0000 0000
10er bit umkopiert in die "neuen" bits:
1111 1110 0000 0000
und voila, eine 16bit signed int variable, die den richtigen wert
enthält.

/Ernst

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Ernst,

dann aber so:
if (val & (1<<9))
  val |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10);


Peter

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter

Da hast Du völlig recht... Zahlen über 5 waren noch nie meine Stärke
;)

/Ernst

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder so: if(val > 511) val -= 1024;

Cheers
Detlef

Autor: m@u (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder so:

if(val&0x100){   // val &  0000 0010 0000 0000
    val|=0xFC00; // val |= 1111 1100 0000 0000
}

Dann hast du doch einen signed int, oder nicht?

Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur mal so zur Info: Beide Varianten funktionieren! Die mit Y=X-1024 und
die mit dem einfügen der Einsen.

Danke nochmals an alle für eure Bemühungen.

Gruß,

Marian

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@m@u:

das ist genau, was der compiler aus dem obigen code macht, die
einzelnen bitshifts+or-Verknüpfungen werden zur compilezeit aufgelöst,
und durch eine Konstante ersetzt.

Hat den Vorteil, dass man sich in einem Jahr nicht fragt, was die
magische "0xFC00" Konstante macht.

/Ernst

Autor: m@u (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Ernst

Dass das der Compiler bereits zur Compilierzeit auflöst habe ich nicht
gewusst, danke!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.