/*
*******************************************************************************
* PIC DIGITAL THERMOMETER USING A MICROCHIP MCP9700A ANALOG SENSOR
*******************************************************************************
*
* source code example for mikroC users
* feel free to use this code at your own risks
*
* target : PIC16F877A, 8 Mhz crystal
* HS clock, no watchdog.
*
* easyPIC4 settings :
* MCP9700A on DS1820 socket, see web page for more details.
*
* Author : Bruno Gavand, September 2007
* see more details on
https://www.micro-examples.com/
*
*******************************************************************************
*/
/*
* LCD_printfix constants
*/
#define INT_RANGE 1000 // integer part : 3 digits
#define DEC_RANGE 10 // decimal part : 1 digit
/*
* this counter is incremented on each TIMER0 overflow
*/
unsigned int cntr ;
long temp ; // Temperature in Celcius * 10
int fahr ; // Temperature in Fahrenheit * 10
/*
* offset reference of the sensor : 0°C is 500 mV => 102.4
* since the sensor is factory calibrated, there is no need for adjustment
*/
int ref = 1024 ; // offset is multiplied by 10 to get tenth of degrees
/*
* LCD character definitions, generated by mikroC LCD Custom Character tool :
*/
const char characterC[] = {8,20,8,0,3,4,4,3}; // °C
const char characterF[] = {8,20,8,0,7,4,6,4}; // °F
/*
* print character pointed to by def at line pos_row column pos_char on LCD
*/
void CustomChar(const char *def, unsigned char n, char pos_row, char pos_char)
{
char i ;
LCD_Cmd(64 + n * 8) ;
for(i = 0 ; i<=7 ; i++)
{
LCD_Chr_Cp(def
) ;
}
LCD_Cmd(LCD_RETURN_HOME) ;
LCD_Chr(pos_row, pos_char, n) ;
}
/*
* print v with fixed-size integer and decimal parts
*/
void LCD_printFix(unsigned int v)
{
unsigned int w ;
unsigned int d ;
unsigned char n ;
unsigned char blk = 1 ; // zero blanking
if(v >= 0)
{
LCD_Chr_Cp('+') ;
}
else
{
LCD_Chr_Cp('-') ;
}
v = abs(v) ;
w = v / DEC_RANGE ;
for(d = INT_RANGE / 10 ; d > 0 ; d /= 10)
{
n = (w / d) % 10 ;
if
{
blk = 0 ;
}
if(blk)
{
LCD_Chr_Cp(' ') ;
}
else
{
LCD_Chr_Cp('0' + n) ;
}
}
LCD_Chr_Cp('.') ;
w = v % DEC_RANGE ;
for(d = DEC_RANGE / 10 ; d > 0 ; d /= 10)
{
LCD_Chr_Cp('0' + (w / d) % 10) ;
}
}
/*
* interrupt routine, called on each timer0 overflow
*/
void interrupt(void)
{
if(INTCON.T0IF) // timer 0 overflow ?
{
cntr++ ; // increment counter
INTCON.T0IF = 0 ; // done
}
}
/*
* program entry
*/
void main()
{
ADCON1 = 0x00 ; // set PORTA as analog input
TRISA = 0xff ; // set PORTA as inputs
TRISD = 0 ; // PORTD is output
LCD_Init(&PORTD) ; // Initialize LCD connected to PORTD
LCD_Cmd(Lcd_CLEAR) ; // Clear display
LCD_Cmd(Lcd_CURSOR_OFF) ; // Turn cursor off
LCD_Out(1, 1, "MCP9700A EXAMPLE"); // Print welcome message
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 sample
{
/*
* read the sensor
*/
temp = Adc_Read(7) * 10 - ref ; // read RE2 ADC, adjust to 0°C
/*
* get the result in celcius * 10
* sensor temperature coefficient is +10mV/°C
* ADC resolution is 5000/1024 = 4.88 mV so one ADC point is 0.488°C
*/
temp *= 488 ;
temp /= 1000 ;
fahr = ((9 * temp) / 5 ) + 320 ; // convert C degrees to F * 10
/*
* print temperature in °C on LCD
*/
LCD_Out(2, 1, "") ;
LCD_printFix(temp) ;
CustomChar(characterC, 0, 2, 7) ;
/*
* print temperature in °F on LCD
*/
LCD_Out(2, 10, "") ;
LCD_printFix(fahr) ;
CustomChar(characterF, 1, 2, 16) ;
cntr = 0 ; // clear counter
}
}
}