zuisti
Advanced Member level 1
On request I wrote a simple and fast function to display the temperature
measured by the Ds3231 internal sensor.
- no any floating operation (integer arithmetic only)
- no any character buffer (each digit is displayed immediately after computed)
From the Ds3231 datasheet:
Temperature is represented as a 10-bit code with a resolution of 0.25°C
and is accessible at location 11h and 12h. The temperature is encoded
in two’s complement format. The upper 8 bits, the integer portion, are
at location 11h and the lower 2 bits, the fractional portion, are in
the upper nibble at location 12h. For example, 00011001 01b = +25.25°C
measured by the Ds3231 internal sensor.
- no any floating operation (integer arithmetic only)
- no any character buffer (each digit is displayed immediately after computed)
From the Ds3231 datasheet:
Temperature is represented as a 10-bit code with a resolution of 0.25°C
and is accessible at location 11h and 12h. The temperature is encoded
in two’s complement format. The upper 8 bits, the integer portion, are
at location 11h and the lower 2 bits, the fractional portion, are in
the upper nibble at location 12h. For example, 00011001 01b = +25.25°C
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 void Ds3231_Temp_CP(void) { // "-00.00", range: -99 to +127 degree // written by (©) zuisti (Istvan K) char msb, lsb, tmp; // read the two temperature registers: I2C1_start(); I2C1_Wr(0xD0); // Ds3231_write address I2C1_Wr(0x11); // register address (temp msb, integer part), to be read first I2C1_Repeated_Start(); I2C1_Wr(0xD1); // Ds3231_read address msb = I2C1_Rd(1); // w. ACK lsb = I2C1_Rd(0); // w. NACK (last read) I2C1_stop(); tmp = ' '; if (msb.B7) { // SIGN_bit = 1: negative tmp = '-'; // two's complement conversion: msb ^= 0xFF; if (!lsb) ++msb; // required if the fractional portion is zero else lsb.B0 = 1; // negative fract. sign, normally it is 0 } else if (msb > 99) { msb -= 100; tmp = '1'; } // the first char is a space, '-' or '1': Lcd_Chr_CP(tmp); // convert msb (binary value) to 2 ASCII digits for ( tmp = '0' ; msb > 9 ; ++tmp, msb -= 10 ); // display integer portion: Lcd_Chr_CP(tmp); Lcd_Chr_CP(msb + '0'); // modulo 10 as ASCII digit // decimal point: Lcd_Chr_CP('.'); // compute fract. part: msb = '0'; tmp = '0'; if (lsb) { // positive 7,6 bits: 01(25), 10(50), 11(75) // negative 7,6 bits: 01(75), 10(50), 11(25) if (!lsb.B6) msb = '5'; // 50 else { msb = '2'; tmp = '5'; if (lsb.B0) // negative fract. (see above): 25 <> 75 lsb.B7 = !lsb.B7; if (lsb.B7) msb = '7'; } } // fract. part Lcd_Chr_CP(msb); Lcd_Chr_CP(tmp); } // end of Ds3231_Temp_CP() // ******** Usage (a possible example): Lcd_Out(1, 1, "Temp:"); Ds3231_Temp_CP(); Lcd_Chr_CP(0xDF); // dec 223 = degree sign Lcd_Chr_CP('C');