Here is the MikroC source code :
/* ******************************************************************************* * PIC DIGITAL THERMOMETER USING A SILICON JUNCTION SENSOR ******************************************************************************* * * how to read temperature with no expensive digital sensor, nor NTC resistor * * source code example for mikroC users * feel free to use this code at your own risks * * target : PIC16F877A * crystal frequency does not matter: any from 4 to 20 Mhz will match, 8 Mhz is good. * HS clock, all flags to mC default values * * EP2/EP3 settings : * JP14 on RE2 * SW2 switches 5 to 8 ON, all others off * pull-down on PORTD * pull-up on keyboard * * this programm has been tested with these kinds of silicon sensors on DS1820 socket : * * SILICON DIODE : * cathode to ground (upper hole), * anode to Vcc thru on-board 4k7 resistor (center hole) * lower hole Vcc is unused * * NPN TRANSISTOR : * emitter to ground (upper hole) * base and collector tied together to Vcc thru on-board 4k7 resistor (center hole) * lower hole Vcc is unused * * MTS102, MTS103, MTS105 sensor : * mount it as a NPN transistor * * instructions for use : * - mount your silicon sensor as described above * - turn on the board * - press RD7 to toggle FAHRENHEIT/CELCIUS display * - take a thermometer and press RD0 or RD1 to adjust the reading on LED display * - cold or heat the sensor to observe the result on LED display * * you will get a 2°C accuracy in the range of ambiant temperatures, * enough for fan control, low cost temperature display, * funny experiments with low-cost devices... * * Author : Bruno Gavand, April 2006 * see more details on www.micro-examples.com * ******************************************************************************* */ /* * keys definition */ #define INCREF PORTD.F0 #define DECREF PORTD.F1 #define UNIT PORTD.F7 /* * segments definition */ #define SA 1 #define SB 2 #define SC 4 #define SD 8 #define SE 16 #define SF 32 #define SG 64 #define DP 128 /* * 7 segments table */ const unsigned char segment[10] = { SA+SB+SC+SD+SE+SF, // 0 SB+SC, // 1 SA+SB+SG+SE+SD, // 2 SA+SB+SG+SC+SD, // 3 SF+SG+SB+SC, // 4 SA+SF+SG+SC+SD, // 5 SA+SF+SG+SE+SC+SD, // 6 SA+SB+SC, // 7 SA+SB+SC+SD+SE+SF+SG, // 8 SA+SB+SC+SD+SF+SG // 9 } ; /* * other symbols */ #define segDEG SA+SB+SF+SG #define segMINUS SG #define segF SA+SE+SF+SG #define segC SA+SD+SE+SF /* * this counter is incremented on each TIMER0 overflow */ long cntr ; /* * display table */ unsigned char data[4] ; /* * current digit to display */ unsigned char dcurr ; /* * fahrenheit degrees flag */ unsigned char fahrenheit = 0 ; /* * result of the measure */ int temp ; /* * offset of the sensor */ int ref = 116 ; /* * convert binary to 7 segment digit, blank on zero is allowed by m */ unsigned char modulo10Seg(unsigned char v, unsigned char m) { return((m || v) ? segment[v % 10] : 0) ; } /* * interrupt routine, called on each timer0 overflow * period does not matter, as long as display does not flicker */ void interrupt(void) { if(INTCON.T0IF) // timer 0 overflow ? { cntr++ ; // increment counter dcurr++ ; // next digit PORTB = 0 ; // turn digit off if(dcurr == 4) // last digit ? { PORTA = 0b00000001 ; // light the first digit dcurr = 0 ; } else { PORTA <<= 1 ; // light the next digit } PORTB = data[dcurr] ; // assign 7 segments value INTCON.T0IF = 0 ; // done } } main() { TRISB = 0 ; // set PORTB as output : 7 segments display PORTB = 0 ; TRISD = 0xff ; // set PORTD as input : keyboard OPTION_REG = 0x80 ; // start timer 0, no prescaler INTCON = 0xA0 ; // allow timer 0 overflow interrupt for(;;) // forever { if(cntr >= 4000) // if enough time since last one { /* * read the sensor */ ADCON1 = 0x00 ; // set PORTA as analog input TRISA = 0xff ; // set PORTA as inputs temp = ref - Adc_Read(7) ; // read RE2 ADC ADCON1 = 0x07 ; // set PORTA as digital IO TRISA = 0 ; // set PORTA as outputs /* * convert to readable value */ temp *= 221 ; // temperature coefficient of the silicon junction temp /= 102 ; temp = 25 + temp ; // get the result in celcius if(fahrenheit) // fahrenheit display enabled ? { temp = ((90 * temp) / 50 ) + 32 ; // convert C degrees to F } if(temp < 0) // value to be displayed is negative ? { data[0] = segMINUS ; // yes, first digit is minus data[1] = modulo10seg(temp / 10, 0) ; // tenths are blanked if zero } else { data[0] = modulo10seg(temp / 100, 0) ; // no, display hundreds (if they are) data[1] = modulo10seg(temp / 10, 1) ; // thenths } data[2] = modulo10seg(temp, 1) ; // units data[3] = fahrenheit ? segF : segC ; // unit symbol cntr = 0 ; // reset counter } /* * process keys */ if(PORTD) // a key is pressed ? { if(INCREF) { ref++ ; // increment the reference data[0] = modulo10seg(ref / 1000, 0) ; // display new reference data[1] = modulo10seg(ref / 100, 1) ; data[2] = modulo10seg(ref / 10, 1) ; data[3] = modulo10seg(ref, 1) ; } else if(DECREF) { ref-- ; // decrement the reference data[0] = modulo10seg(ref / 1000, 0) ; // display new reference data[1] = modulo10seg(ref / 100, 1) ; data[2] = modulo10seg(ref / 10, 1) ; data[3] = modulo10seg(ref, 1) ; } else if(UNIT) { fahrenheit = !fahrenheit ; // toggle celcius / fahrenheit /* * display new unit */ data[0] = 0 ; data[1] = segDEG ; if(fahrenheit) { data[2] = segF ; } else { data[2] = segC ; } data[3] = 0 ; } while(PORTD) ; // wait for the key to be released cntr = 0 ; // reset counter } } }