Forum: Mikrocontroller und Digitale Elektronik DS18S20 - extended resolution bei Temperaturen um 0°C


von Biff (Gast)


Lesenswert?

Hallo,

ich beschäftige mich seit einiger Zeit mit dem DS18S20. Nun habe ich 
versucht, die Temperatur für Auflösungen größer 9Bit gemäß der Formel im 
Datenblatt zu berechnen:


Das funktioniert auch, nur bei Minus-Temperaturen um die 0°C zeigt mir 
mein Display riesige Werte an. Ich vermute, dass der Fehler daraus 
resultiert, dass mir der Sensor für COUNT_REMAIN Werte größer 12 schickt 
und TEMP_READ nach der notwendigen Zweierkomplementbildung 0 ist. Damit 
hätte ich bei der Addition am Ende einen negativen Wert, der meine 
riesigen Werte erklären würde. Muss ich das ganze irgendwie 
softwareseitig abfangen, also z.B. durch folgende Prüfung?
1
if ((TEMP_READ == 0) && (COUNT_REMAIN > 12))
2
{
3
COUNT_REMAIN = 12;
4
}

Zur Zeit habe ich das so realisiert, nur eigentlich geht mir dann mit 
dieser Abfrage Genauigkeit verloren. Hat irgendjemand dasselbe Problem 
und dafür eine Lösung parat?

Danke,

Biff

von Karl H. (kbuchegg)


Lesenswert?

Biff schrieb:

> Ich vermute

Das ist ganz schlecht.
Mit Vermutungen kann man kein Programm schreiben.
Lass dir die Werte ausgeben, dann WEISST du es!

(und kannst nebenbei auch mal händisch alles durchrechnen und nachsehen, 
was sich bei Zwischenergebnissen so alles tut)

Ich denke, du hast eher irgendwo einen signed-unsigned Fehler. Aber ohne 
Code und dem Wissen über die beteiligten Datentypen der Variablen sind 
das alles nur Mutmassungen.

von Biff (Gast)


Lesenswert?

Hallo,

anbei die Funktion, die die Werte vom DS18S20 ausliest. Bei der 
Berechnung habe ich bereits verschiedene Versionen ausprobiert, da ich 
erst dachte, dass es an meiner Formel liegt. Ich habe dann eine andere 
Berechnung genutzt, aber auch da habe ich das gleiche Problem.
1
uint16_t w1_getmultitemp(uint8_t actsensor)
2
3
  {
4
5
    uint8_t i, temp_msb = 0;
6
    uint16_t temp = 0, temp_lsb = 0, count_remain = 0;
7
    
8
    
9
10
    w1_reset();
11
12
    w1_writebyte(MATCH_ROM);                  //1wire: Match ROM-Befehl senden
13
14
    for (i = 0; i < 8; i++)
15
    {
16
    
17
      w1_writebyte(sensor[actsensor][i]);            //Sensor-Adresse senden
18
     }
19
20
    w1_writebyte(CONVERT_T);                  //1wire: Convert T-Befehl senden
21
22
    w1_ready();
23
24
    w1_reset();
25
     w1_writebyte(MATCH_ROM);                  //1wire: Match ROM-Befehl senden
26
27
    for (i = 0; i < 8; i++)
28
    {
29
    
30
      w1_writebyte(sensor[actsensor][i]);            //Sensor-Adresse senden
31
     }
32
33
    w1_writebyte(READ_SP);                    //1wire: Convert T-Befehl senden
34
35
36
    temp_lsb = w1_readbyte();                  //Temperatur LSB
37
    temp_msb = w1_readbyte();                  //Temperatur MSB
38
    w1_readbyte();                        //Th-Register
39
    w1_readbyte();                        //Tl-Register
40
    w1_readbyte();                        //Reserve (0xFF)
41
    w1_readbyte();                        //Reserve (0xFF)
42
    count_remain = w1_readbyte();                //count remain
43
    w1_readbyte();                        //count per°C (0x10)
44
    w1_readbyte();                        //CRC
45
46
    w1_reset();
47
48
    if (temp_msb)                        //wenn die Temperatur < 0°C
49
    {
50
      temp_lsb = (~temp_lsb + 1) & 0x00FF;          //2er-Komplement
51
    }
52
53
    //neue Version der Berechnung:
54
    temp_lsb = temp_lsb >> 1;
55
    temp_lsb = temp_lsb << 4;                  //Multiplikation mit 16
56
    temp = temp_lsb + 12;
57
58
    if ((temp_lsb == 0) && (count_remain > 12))
59
    {
60
    temp = temp - 12;
61
    }
62
63
    else
64
    {
65
    temp = temp - count_remain;
66
    }
67
68
    temp = temp * 25;
69
    temp = temp >> 2;                      //Division mit 4
70
71
    /*alte Version der Berechnung:
72
    temp_lsb = temp_lsb >> 1;
73
    temp_lsb = temp_lsb * 100;
74
75
    count_remain = count_remain * 100;
76
    count_remain = count_remain >> 4;              //Division durch 16
77
78
    temp = temp_lsb - 25 + 100 - count_remain;
79
    */
80
81
    if (temp_msb)                        //wenn die Temperatur < 0°C
82
    {
83
      temp = temp | 0x8000;                  //Setzen des MSB als Indikator für Minustemperaturen
84
    }
85
  
86
87
    return(temp);
88
89
  }


Meine Frage ist, ob der Sensor bei Minus-Temperaturen überhaupt die 
Kombination TEMP_READ = 255 und COUNT_REMAIN > 12 schickt? Weil dann 
käme es bei der Formel im Datenblatt zu einem negativen Resultat, 
nachdem man das Zweierkomplement von TEMP_READ gebildet und den Wert 
einmal nach rechts geschoben hat.

Danke,

Biff

von visitor (Gast)


Lesenswert?

Müsste die Zeile nicht verodert werden ?

if ((TEMP_READ == 0) || (COUNT_REMAIN > 12))
{
COUNT_REMAIN = 12;
}

von Biff (Gast)


Lesenswert?

Hallo visitor,

eigentlich ja nicht, da es dieses Problem mit der Formel ja nur dann 
gibt, wenn der Wert TEMP_READ == 0 ist und COUNT_REMAIN > 12 ist. Wenn 
eine der Bedingungen nicht erfüllt ist, dann kann es gemäß der Formel ja 
nicht passieren, dass am Ende der Subtraktion ein Wert kleiner 0 
herauskommt. Deswegen habe ich diese beiden Bedingungen "verunded".

Biff

von 900ss (900ss)


Lesenswert?

Der Sensor funktioniert so wie du es möchtest. Hab ihn selber schon mal 
so benutzt. Nur du rechnest falsch und verschluderst wahrscheinlich 
irgendwo Vorzeichen. Überall nur uint Variablen. Denk mal drüber nach, 
prüfe alle Zwischenergebnisse und du kommst selber drauf. Karl-Heinz 
schrieb es ja auch schon oben.

von Biff (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe jetzt mal Karl-Heinz' Ratschlag befolgt und mir die Messwerte 
ausgeben lassen. Die Kombination aus TEMP_READ == 0 und COUNT_REMAIN 
scheint es nicht zu geben. Für alle die es interessiert ist im Anhang 
der Log, interessant für mein Problem sind die Zeilen 169-228. Somit 
liegt mein Problem in meiner Berechnung. Ich werde mal gucken, ob ich 
hier im Forum ein Beispielcode finde. Danke erstmal,

Biff.

von Gustl (Gast)


Lesenswert?

Hi,

ich hatte in der Vergangenheit auch schon mal dass Problem. Meine Lösung 
:

// Temperatur = (((16*aucScratchpad[0])+12-aucScratchpad[6])*25)/4

usExtTemperature =  (aucScratchpad[0]>>1);
usExtTemperature = usExtTemperature * 16;
usExtTemperature = usExtTemperature + 12;
if(aucScratchpad[6] > 12)
{
  usExtTemperature = usExtTemperature - 12;
}
else
{
  usExtTemperature = usExtTemperature - aucScratchpad[6];
}
usExtTemperature = usExtTemperature * 25;
usExtTemperature = usExtTemperature >> 2;

von eProfi (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für die aufschlussreichen Logs, leider fehlen ein paar 
Zeilen, z.B.
000;000;075;070;255;255;016;016;

Es gibt etliche Fallstricke beim Rechnen mit signed ints, z.B. (-1)/2=+0

Wer seinen Algorithmus testen will, hier die korrekte Zuordnung:
Mein Testobjekt: DS1820 von Pollin 180014 (2,50)
1
 0  1   6  7  9bit   12bit  12bit-Äquivalent
2
ff 00  01 10 127,5 127,6875  07fb  max. Temp (lötkolbengetestet ;-))
3
ff 00  02 10 127,5 127,6250  07fa
4
ff 00  03 10 127,5 127,5625  07f9
5
ff 00  04 10 127,5 127,5000  07f8
6
ff 00  05 10 127,5 127,4375  07f7
7
ff 00  06 10 127,5 127,3750  07f6
8
ff 00  07 10 127,5 127,3125  07f5
9
ff 00  08 10 127,5 127,2500  07f4
10
ff 00  09 10 127,0 127,1875  07f3
11
....
12
02 00  0c 10   1,0   1,0000  0010
13
02 00  0d 10   1,0   0,9375  000F
14
02 00  0e 10   1,0   0,8750  000E
15
02 00  0f 10   1,0   0,8125  000D
16
02 00  10 10   1,0   0,7500  000C
17
01 00  01 10   0,5   0,6875  000B
18
01 00  02 10   0,5   0,6250  000A
19
01 00  03 10   0,5   0,5625  0009
20
01 00  04 10   0,5   0,5000  0008
21
01 00  05 10   0,5   0,4375  0007
22
01 00  06 10   0,5   0,3750  0006
23
01 00  07 10   0,5   0,3125  0005
24
01 00  08 10   0,5   0,2500  0004
25
00 00  09 10   0,0   0,1875  0003
26
00 00  0a 10   0,0   0,1250  0002
27
00 00  0b 10   0,0   0,0625  0001
28
00 00  0c 10   0,0   0,0000  0000
29
00 00  0d 10   0,0  -0,0625  ffff
30
00 00  0e 10   0,0  -0,1250  fffe
31
00 00  0f 10   0,0  -0,1875  fffd
32
00 00  10 10   0,0  -0,2500  fffc
33
ff ff  01 10  -0,5  -0,3125  fffb
34
ff ff  02 10  -0,5  -0,3750  fffa
35
ff ff  03 10  -0,5  -0,4375  fff9
36
ff ff  04 10  -0,5  -0,5000  fff8
37
ff ff  05 10  -0,5  -0,5625  fff7
38
ff ff  06 10  -0,5  -0,6250  fff6
39
ff ff  07 10  -0,5  -0,6875  fff5
40
ff ff  08 10  -0,5  -0,7500  fff4
41
fe ff  09 10  -1,0  -0,8125  fff3
42
fe ff  0a 10  -1,0  -0,8750  fff2
43
fe ff  0b 10  -1,0  -0,9375  fff1
44
fe ff  0c 10  -1,0  -1,0000  fff0
45
fe ff  0d 10  -1,0  -1,0625  ffef
46
fe ff  0e 10  -1,0  -1,1250  ffee
47
fe ff  0f 10  -1,0  -1,1875  ffed
48
fe ff  10 10  -1,0  -1,2500  ffec
49
fd ff  01 10  -1,5  -1,3125  ffeb
Für die 12bit-4Nachkommastellen-Ausgabe kann man die die Periodizität 
nutzen: die letzten beiden Ziffern sind jedes 4. Mal gleich.

Ich gebe nur 2 Nachkommastellen mit LookUp aus:
char s[32]="00061319253138445056636975818894";
if(temp12<0){tabs12=-temp12;sign='-';}else{tabs12=temp12;sign='+';}
...
put(s[help=2*(tabs12&15)];put(s[help+1]);

In den Anhängen findet Ihr ein neues Testfile (gleich aufgebaut wie die 
o.g. Logs), ein Programm, das das Testfile auf verschiedene Arten 
umrechnet und die Ausgabe dieses Programms.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Wozu soll das hier gut sein

    if (temp_msb)                        //wenn die Temperatur < 0°C
    {
      temp_lsb = (~temp_lsb + 1) & 0x00FF;          //2er-Komplement
    }


Ich würde ehrlich gesagt da nicht grossartig auf Bitebene rumpfriemeln.

Du kriegst erst mal die beiden Bytes für die Temperatur. Die werden vom 
DS freundlicherweise schon im 2-er Komplement geschickt.
D.h. die beiden Bytes setzt ich in einer int16_t Variablen zusammen und 
hab dann schon einen fix/fertigen Wert (inklusive Vorzeichen), der dem 
doppelten der tatsächlichen Temperatur entspricht.

Und ab da rechne ich alles nur noch mit signed integer Variablen 
(int16_t), so wie es im Datenblatt angegegeben ist, wobei ich es 
tunlichst unterlasse schlauer als mein Compiler zu sein.

von JoachimB (Gast)


Lesenswert?

Hallo Biff,

wo lässt Du den Wert "count per °C" ?
Soweit ich deinen Code verstanden habe, liest Du den Wert Count_per_C 
nicht in eine Variable. Du kannst deshalb in deiner Berechnung auch 
keine sinnvollen Ergebnisse erzielen.
das Geheimnis der Sensoren besteht darin, dass die Spanne von einem Grad 
Celsius eine Anzahl Counts liefert, die sich über den Messbereich 
ändert.
z.B. von 10-11°C 73 Counts und von 20 bis 21°C 80 Counts.

Gruß
Joachim

von Bingo (Gast)


Lesenswert?

Siehe hier

http://gandalf.arubi.uni-kl.de/avr_projects/tempsensor/index.html
http://gandalf.arubi.uni-kl.de/avr_projects/tempsensor/ds18x20_demo_20100715c.zip

Und extended temp for 18s20 - the easy way
1
  //  only work on 12bit-base
2
3
  if( fc == DS18S20_FAMILY_CODE ) { // 9 -> 12 bit if 18S20
4
5
    /* Extended res. measurements for DS18S20 contributed by Carsten Foss */
6
7
    meas &= (uint16_t) 0xfffe;    // Discard LSB, needed for later extended precicion calc
8
9
    meas <<= 3;                   // Convert to 12-bit, now degrees are in 1/16 degrees units
10
11
    meas += ( 16 - sp[6] ) - 4;   // Add the compensation and remember to subtract 0.25 degree (4/16)
12
13
  }

/Bingo

von Carsten W. (carsten_w)


Lesenswert?

Hi,

hier ist noch ein Beispiel:
1
...
2
int tmp;
3
...
4
DIS.E[i].Value = OWIReceiveByte(Pin);
5
DIS.E[i].Value |= (OWIReceiveByte(Pin) << 8);
6
OWIReceiveByte(Pin);
7
OWIReceiveByte(Pin);
8
OWIReceiveByte(Pin);
9
OWIReceiveByte(Pin);
10
tmp = DIS.E[i].Value >> 1;
11
tmp = tmp << 4;
12
tmp -= 4;
13
tmp += (16 - OWIReceiveByte(Pin));
14
DIS.E[i].Value = tmp;
15
...

Gruß
Carsten

von eProfi (Gast)


Lesenswert?

Von mir wieder einmal ein Runde Kraftfutter,
HighDensityCode vom Feinsten:

Die komplette Auswertung des gelesenen Temperaturwertes samt
 - Umwandlung in druckbare Zeichen,
 - Unterdrückung führender Nullen,
 - Verschiebung des Vorzeichens
 - zwei Nachkommastellen
in 10 Zeilen (ohne die Kommentare). Ich kann gar nicht verstehen, wie 
man hierfür kilometerlangen Code schreiben kann.

Ohne Verwendung von printf, *, / oder % ,
ergibt auch auf kleinen µC einen Mini-Code.
1
unsigned char d[9]; //Dallas DS1820 Scratchpad
2
int t; //absolute degrees
3
int f; //fractions (1/16ø) of absolute degrees
4
//char,fractional digits and the
5
//sign (if zero, the sign was already printed)
6
char c,g[16]="0011233455667889",h[16]="0639518406395184",s;
7
8
if(d[1]){s='-';f=(4+d[6])&15;
9
  if(d[6]>11)t=128-d[0]/2;else t=127-d[0]/2;}
10
else{s='+';t=d[0]/2  ;f=(28-d[6])&15;
11
  if(d[6]>12){if(d[0]){t--;}else{s='-';f=d[6]-12;}}}
12
13
if(t>99){putch(  s);s=0;putch('1');t-=100;}
14
else    {putch(' ');if(t>9){putch(s);s=0;}else putch(' ');}
15
c='0';while((t-= 10)>=0)c++;if(s)putch(s);else{putch(c);}
16
putch(58+t);putch(',');putch(g[f]);putch(h[f]);putch('°');putch('C');


Hier die Vorversion ohne 0-Unterdrückung und Vorzeichenverschieben
7 Zeilen ;-)
1
if(d[1]){c='-';f=(4+d[6])&15;
2
  if(d[6]>11)t=128-d[0]/2;else t=127-d[0]/2;}
3
else{c='+';t=d[0]/2;f=(28-d[6])&15;
4
  if(d[6]>12){if(d[0]){t--;}else{c='-';f=d[6]-12;}}}
5
6
putch(c);if(t>99){putch('1');t-=100;}else putch('0');
7
c=47;while(c++,(t-=10)>=0);putch(c);putch(58+t);
8
putch(',');putch(g[f]);putch(h[f]);putch('°');putch('C');


Code funktioniert nur bei Sensoren, die als CountPerDegree fest 16 
haben.

Für die gibt eine weitere Berechnung des 12-Bit-Wertes:
1
if(a[1]){temp12=63491+8*a[0]-((a[6]-1)&7);}
2
else    {temp12=    3+8*a[0]-((a[6]-1)&7);}
3
if(temp12<0){tabs12=-temp12;sign='-';} //Absolutwert berechnen
4
else        {tabs12= temp12;sign='+';}
5
6
frac=tabs12&15;//Nachkomma in 1/16°
7
grad=tabs12/16;//muss signed sein, damit divBySub funktioniert

Guten Appetit!
Anregungen, Kommentare, Verbesserungen ... immer gern gesehen!

von holger (Gast)


Lesenswert?

>in 10 Zeilen (ohne die Kommentare). Ich kann gar nicht verstehen, wie
>man hierfür kilometerlangen Code schreiben kann.

Weil es übersichtlicher ist und nicht so ein scheisse
formatierter Schrott wie von dir.

von eProfi (Gast)


Lesenswert?

Von mir wieder einmal ein Runde Kraftfutter,
HighDensityCode vom Feinsten:

Die komplette Auswertung des gelesenen Temperaturwertes samt
 - Umwandlung in druckbare Zeichen,
 - Unterdrückung führender Nullen,
 - Verschiebung des Vorzeichens
 - zwei Nachkommastellen
in 10 Zeilen (ohne die Kommentare). Ich kann gar nicht verstehen, wie 
man hierfür kilometerlangen Code schreiben kann.

Ohne Verwendung von printf, *, / oder % ,
ergibt auch auf kleinen µC einen Mini-Code.
1
unsigned char d[9]; //Dallas DS1820 Scratchpad
2
int t; //absolute degrees
3
int f; //fractions (1/16°) of absolute degrees
4
//char,fractional digits and the
5
//sign (if zero, the sign was already printed)
6
char c,g[16]="0011233455667889",h[16]="0639518406395184",s;
7
8
if(d[1]){s='-';f=(4+d[6])&15;
9
  if(d[6]>11)t=128-d[0]/2;else t=127-d[0]/2;}
10
else{s='+';t=d[0]/2;f=(28-d[6])&15;
11
  if(d[6]>12){if(d[0]){t--;}else{s='-';f=d[6]-12;}}}
12
13
if(t>99){putch(  s);s=0;putch('1');t-=100;}
14
else    {putch(' ');if(t>9){putch(s);s=0;}else putch(' ');}
15
c='0';while((t-=10)>=0)c++;if(s)putch(s);else putch(c);
16
putch(58+t);putch(',');putch(g[f]);putch(h[f]);putch('°');putch('C');


Hier die Vorversion ohne 0-Unterdrückung und Vorzeichenverschieben
7 Zeilen ;-)
1
if(d[1]){c='-';f=(4+d[6])&15;
2
  if(d[6]>11)t=128-d[0]/2;else t=127-d[0]/2;}
3
else{c='+';t=d[0]/2;f=(28-d[6])&15;
4
  if(d[6]>12){if(d[0]){t--;}else{c='-';f=d[6]-12;}}}
5
6
putch(c);if(t>99){putch('1');t-=100;}else putch('0');
7
c=47;while(c++,(t-=10)>=0);putch(c);putch(58+t);
8
putch(',');putch(g[f]);putch(h[f]);putch('°');putch('C');


Code funktioniert nur bei Sensoren, die als CountPerDegree fest 16 
haben.

Für die gibt eine weitere Berechnung des 12-Bit-Wertes:
1
if(d[1]){temp12=63491+8*d[0]-((d[6]-1)&7);}
2
else    {temp12=    3+8*d[0]-((d[6]-1)&7);}
3
if(temp12<0){tabs12=-temp12;sign='-';} //Absolutwert berechnen
4
else        {tabs12= temp12;sign='+';}
5
6
frac=tabs12&15;//Nachkomma in 1/16°
7
grad=tabs12/16;//muss signed sein, damit divBySub funktioniert

Guten Appetit!
Anregungen, Kommentare, Verbesserungen ... immer gern gesehen!


Also gut, hier formatiert und kommentiert:
Habe den Code noch minimal geändert. Für t und f reicht  char.
Das sind ein paar hundert Bytes Code.
1
//Idea and code (C) by eProfi
2
//for better understanding  look at the table in
3
//www.mikrocontroller.net/topic/202928#1999183
4
//output format:
5
//  1      2      3    4  5   6    7
6
//sign hundreds tens ones , 1/10 1/100
7
8
const PROGMEM char
9
  g[16]="0011233455667889",//first  fractional digit
10
  h[16]="0639518406395184",//second fractional digit
11
12
unsigned char d[9];     //Dallas DS1820 Scratchpad
13
char t;                 //temperature in absolute degrees
14
char f;                 //fractionals (1/16°) of absolute degrees
15
char c,s;               //sign (if zero, the sign was printed already)
16
17
if(d[1]){s='-';         //case1 : temp is -0.31 or lower --> negative anyways
18
  f=(4+d[6])&15;
19
  t=127-d[0]/2;         //case1a: temp is -x.31 to -x.94 --> "round down"
20
  if(d[6]>11)t++;}      //case1b: temp is -x.00 to -x.25 --> "round up"
21
else{s='+';t=d[0]/2;    //case2 : temp is -0.25 or higher
22
  f=(28-d[6])&15;
23
  if(d[6]>12){          //case2a: temp is  x.81 to  x.94  or  -0.25 to -0.06
24
    if(d[0])t--;        //case2b: temp is  x.81 to  x.94 --> "round down"
25
    else{s='-';         //case2c: temp is -0.25 to -0.06, overwrite +sign
26
      f=d[6]-12;}}}     //        and recalc fractionals
27
28
if(t>99){putch(s);s=0;  //absolute temp is higher than 99 (and lower than 128)
29
  putch('1');t-=100;}   //sign-digit is the sign, hund-digit is 1
30
else{putch(' ');        //absolute temp is lower than 100, sign-digit is a space
31
  if(t>9){putch(s);s=0;}//if 10..99: hund-digit is the sign
32
  else    putch(' ');}  //if  0.. 9: hund-digit is a space
33
34
c='0'-1;                //calculate tens
35
while(c++,(t-=10)>=0);  //this should be faster than c='0';while((t-=10)>=0)c++;
36
if(s)putch(s);          //if sign was not printed yet, do it now at tens-digit
37
else putch(c);          //tens-digit
38
39
putch(58+t);putch(',' );//ones-digit   '0'+10+t, as t is negative here
40
putch(g[f]);putch(h[f]);//the fractional digits are not calculated
41
putch('°' );putch('C' );//but stored in 2 arrays




Und hier der komplette Code für die Berechnung über den 12bit-Wert:
1
//Idea and code (C) by eProfi
2
//for better understanding  look at the table in
3
//www.mikrocontroller.net/topic/202928#1999183
4
//output format:
5
//  1      2      3    4  5   6    7
6
//sign hundreds tens ones , 1/10 1/100
7
8
const PROGMEM char
9
  g[16]="0011233455667889",//first  fractional digit
10
  h[16]="0639518406395184",//second fractional digit
11
12
  unsigned char d[9];     //Dallas DS1820 Scratchpad
13
  char t;                 //temperature in absolute degrees
14
  char f;                 //fractionals (1/16°) of absolute degrees
15
  char c,s;               //sign (if zero, the sign was printed already)
16
  int  t12;               //12bit temperature value
17
18
  t12=3+8*a[0]-((a[6]-1)&7);//alternate way of calculation
19
  if(a[1]){t12-=128*16;}  //correct by -128°
20
  if(t12>=0){s='+';}      //calc absolute temp
21
  else{t12=-t12;s='-';}
22
23
  f=t12&15;               //fractionals
24
  t=t12>>4;//must be signed int  for the calculation of tens-digit (while)
25
26
  if(t>99){putch(s);s=0;  //absolute temp is higher than 99 (and lower than 128)
27
    putch('1');t-=100;}   //sign-digit is the sign, hund-digit is 1
28
  else{putch(' ');        //absolute temp is lower than 100, sign-digit is a space
29
    if(t>9){putch(s);s=0;}//if 10..99: hund-digit is the sign
30
    else    putch(' ');}  //if  0.. 9: hund-digit is a space
31
32
  c='0'-1;                //calculate tens
33
  while(c++,(t-=10)>=0);  //this should be faster than c='0';while((t-=10)>=0)c++;
34
  if(s)putch(s);          //if sign was not printed yet, do it now at tens-digit
35
  else putch(c);          //tens-digit
36
37
  putch(58+t);putch(',' );//ones-digit   '0'+10+t, as t is negative here
38
  putch(g[f]);putch(h[f]);//the fractional digits are not calculated
39
  putch('°' );putch('C' );//but stored in 2 arrays

von eProfi (Gast)


Lesenswert?

Grrr..
Vergesst die erste Hälfte des Posts, ist die Kopie des oberen.
Der neuen Codes steht in der zweiten Hälfte.

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.