Forum: Mikrocontroller und Digitale Elektronik Negative Werte ausgeben


von Florian M. (lauch_henne)


Lesenswert?

Hallo Community,

ich programmiere gerade an einem DS1621 und möchte gerne negative 
Temperaturen lesen. Das ganze funktioniert mit dem Zweierkomplement.
Bisher habe ich folgenden Code geschrieben, doch leider funktioniert er 
nicht wie erwünscht.
Ich erreiche damit schonmal einen Minusvorzeichen, allerdings gibt er 
mir immer noch für Werte unter 0: 255 und abwärts aus..
Auch stimmt die Abfrage im If-Block wohl nicht ganz.
Nicht wundern, ich habe beim Auskommentieren Block bisschen rumprobiert.
Anbei der Code:

1
if(temp&&0x01 == 0x00)
2
{
3
  printf("   Temperatur: %d [C]\r",temp);
4
  delayMs(0,500);
5
6
7
}
8
else
9
{
10
  temp=~temp; //Wert negieren
11
  temp_low = temp + 0x01; //eins dazuzählen
12
  //temp_low = temp_low + 0x01; //temp_low &
13
  //temp &= ~(1>>7);
14
  printf("%d", temp_low);
15
  delayMs(0,500);
16
}

Kann mir da jmd weiterhelfen? Steh echt auf dem Schlauch...
Danke!

: Bearbeitet durch User
von Michael (Gast)


Lesenswert?

Florian Müller schrieb:
> if(temp&&0x01 == 0x00)

Ohne jetzt deine Variablendeklaration zu kennen und zu wissen was in 
temp steht, solltest du vielleicht ein C-Buch konsultieren.

Was soll dieses Konstrukt bewirken. "&&" ist der Operator für logisches 
UND und nicht für Bitweises UND. Und was verleitet dich zu der Annahme, 
dass das Vorzeichenbit ausgerechnet im untersten Bit von temp steht?

von Florian M. (lauch_henne)


Lesenswert?

[quote]Ohne jetzt deine Variablendeklaration zu kennen und zu wissen was 
in
temp steht, solltest du vielleicht ein C-Buch konsultieren.[/quote]
Ja du hast vielleicht Recht :P
Schande über mein Haupt!

[quote]Was soll dieses Konstrukt bewirken. "&&" ist der Operator für 
logisches
UND und nicht für Bitweises UND. Und was verleitet dich zu der Annahme,
dass das Vorzeichenbit ausgerechnet im untersten Bit von temp 
steht?[/quote]

Eigentlich wollte ich die Bedingung stellen, dass wenn Temp kleiner 0 
ist, er die Anweisung befolgt.
Eigentlich sitzt das Vorzeichenbit an vorderster Front (MSBfirst)

: Bearbeitet durch User
von innerand i. (innerand)


Lesenswert?

Florian Müller schrieb:

>
> Eigentlich wollte ich die Bedingung stellen, dass wenn Temp kleiner 0
> ist, er die Anweisung befolgt.

Warum dann nicht einfach so hinschreiben?

Im übrigen kommen die Werte vom DS1621 bereits im Zweierkomplement.
Ich denke dein Problem liegt im zweiten Byte das da noch daher kommt und 
die halben Grad darstellt (über das msb).

Kuckst du hier http://www.mikrocontroller.net/part/DS1621 auf Seite 4.

von Karl H. (kbuchegg)


Lesenswert?

> Auch stimmt die Abfrage im If-Block wohl nicht ganz.

schon.
Aber wozu das ganze?
Das kann printf alleine auch. Einfach dafür sorgen, dass die Datentypen 
stimmen, und man braucht sich überhaupt nicht mehr selbst darum kümmern.

Also: Welchen Datentyp hat temp?

Auch wenn man in den meisten µC Programmen mit unsigned char (oder 
uint8_t) arbeiten, braucht man hier nur rechtzeitig und an der richtigen 
Stelle die Kurve zu int (oder int16_t) kratzen, und schon braucht man 
sich um die Sache mit dem 2-er Komplement überhaupt nicht mehr kümmern. 
Genau deswegen benutzt das der ds1621 nämlich in erster Linie, weil es 
für alle Computer bzw. Programmiersprachen völlig normal ist, dass 
vorzeichenbehaftete Werte bzw Variablen mit ihm arbeiten und daher auch 
alle Ein-/Ausgabefunktionen bzw. Rechenoperationen dafür ausgelegt ist.
Der Hinweis '2-er Komplement' im Datenblatt ist für dich einfach nur der 
Hinweis, dass die Zielvariable, in die du die beiden Bytes reinklopfen 
musst (und zwar genau so, wie du sie kriegst) einfach nur ein signed 
Datentyp sein soll. In C ist das dann eben ein int, ein signed char, ein 
int8_t, ein int16_t, long, int32_t oder was du eben sonst noch so hast, 
was mit einem Vorzeichen umgehen kann.

: Bearbeitet durch User
von Florian M. (lauch_henne)


Lesenswert?

Karl Heinz schrieb:
>> Auch stimmt die Abfrage im If-Block wohl nicht ganz.
>
> schon.
> Aber wozu das ganze?
> Das kann printf alleine auch. Einfach dafür sorgen, dass die Datentypen
> stimmen, und man braucht sich überhaupt nicht mehr selbst darum kümmern.

Achso, du meinst die Funktion "printf" pickt sich dann schon den 
richtigen Wert raus?

> Also: Welchen Datentyp hat temp?

int temp;
Damit hab ich es mal probiert..Allerdings spuckt er mir bei den 
negativen Werten leider 256 und absteigend aus..wobei aber alle meine 
Variablen den Wert int besitzen.

> Auch wenn man in den meisten µC Programmen mit unsigned char (oder
> uint8_t) arbeiten, braucht man hier nur rechtzeitig und an der richtigen
> Stelle die Kurve zu int (oder int16_t) kratzen, und schon braucht man
> sich um die Sache mit dem 2-er Komplement überhaupt nicht mehr kümmern.
> Genau deswegen benutzt das der ds1621 nämlich in erster Linie, weil es
> für alle Computer bzw. Programmiersprachen völlig normal ist, dass
> vorzeichenbehaftete Werte bzw Variablen mit ihm arbeiten und daher auch
> alle Ein-/Ausgabefunktionen bzw. Rechenoperationen dafür ausgelegt ist.
> Der Hinweis '2-er Komplement' im Datenblatt ist für dich einfach nur der
> Hinweis, dass die Zielvariable, in die du die beiden Bytes reinklopfen
> musst (und zwar genau so, wie du sie kriegst) einfach nur ein signed
> Datentyp sein soll. In C ist das dann eben ein int, ein signed char, ein
> int8_t, ein int16_t, long, int32_t oder was du eben sonst noch so hast,
> was mit einem Vorzeichen umgehen kann.

Ich schreibe in einen Buffer den Wert byte1, in einem zweiten Buffer den 
Wert byte2..anschließend muss ich dann wohl die beiten bytes einfach zu 
einem zusammenfassen und es als temp ausgeben.
Anbei habe ich mal den ganzen Code angehängt.
1
 init_lcd();
2
3
4
  I2CWriteLength[PORT_USED] = 2;      //Address byte + Data byte
5
  I2CReadLength[PORT_USED] = 0;      //Write only
6
  I2CMasterBuffer[PORT_USED][0] = 0x90;// DS1621_ADDR;  //I2C Adresse des Slaves
7
  I2CMasterBuffer[PORT_USED][1] = 0xEE;
8
  I2CEngine(PORT_USED);
9
  delayMs(0,1000);
10
11
  while(1)  
12
     {
13
14
15
  I2CWriteLength[PORT_USED] = 2;
16
  I2CReadLength[PORT_USED]= 1;    //
17
  I2CMasterBuffer[PORT_USED][0] = 0x90; 
18
  I2CMasterBuffer[PORT_USED][1] = READ_TEMPERATURE;
19
  I2CMasterBuffer[PORT_USED][2] = DS1621_ADDR | RD_BIT;
20
  I2CEngine(PORT_USED);
21
  delayMs(0,1000);
22
23
  byte1 = I2CSlaveBuffer[PORT_USED][0];                                     //Read out byte 1 from slave buffer
24
  //byte2 = I2CSlaveBuffer[PORT_USED][0];
25
26
      //temp = (byte2 |= (byte1<<8));  //Ab hier und drunter ist alles ok! Oben ist iwo das Problem..natürlich noch an meinen ds anpassen!
27
      //temp = (0,25*(var>>5));
28
      //temp = byte1/100;// + byte2;
29
temp = byte1;
30
31
if(temp&&0x01 == 0x00)
32
{
33
  printf("   Temperatur: %d [C]\r",temp);
34
  delayMs(0,500);
35
36
37
}
38
else
39
{
40
  //temp=~temp;
41
  temp_low = ~temp + 0x01;
42
  //temp_low = temp_low + 0x01; //temp_low &
43
  //temp &= ~(1>>7);
44
  printf("%d", temp_low);
45
  delayMs(0,500);
46
}
47
     }
48
return 0;
49
}

von innerand i. (innerand)


Lesenswert?

Florian Müller schrieb:

> Ich schreibe in einen Buffer den Wert byte1, in einem zweiten Buffer den
> Wert byte2..anschließend muss ich dann wohl die beiten bytes einfach zu
> einem zusammenfassen und es als temp ausgeben.
> Anbei habe ich mal den ganzen Code angehängt.

Nein, einfach zusammenfassen ist hier nicht.
Hier steht ein Byte für einen int der die Temperatur in ganzen Grad 
darstellt (negative eben im Zweierkomplement).
Vom anderen Byte zählt nur das MSB und gibt an ob noch ein halbes Grad 
dazu kommt oder nicht.

byte2.7 = 1 --> + 0.5 Grad
byte2.7 = 0 --> + 0 Grad

Wie gesagt, Doku lesen.

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.