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
}
}
}