```//  MCP9701_1.c, Temperature Measurement using a MCP9701A
//
// copyright, Peter H. Anderson, Baltimore, MD, April, '23, '10

#ifdef DESCRIPTION

Continually measure the output of a Microchip MCP9701A on AN0.  Calculates
temperature in degrres C and degrees F and displays to LCD.

Note that function;

performs the specified number of A/D readings and averages.

There are up to 12 A/D channels, seven in terminals associated with PORTB
and five with PORTA.  The ANSELA and ANSELB registers control whether a terminal
is configured with an A/D input or a digital input.  A point of minor confusion
is that the bits in ANSELB map into the PORTB bits and not the A/D.  For
example, bit ANSB3 corresponds to PORTB3 which is AN9.

a host of voltage reference options.

********************

The MCP9701A is an inexpensive temperature sensor available in a TO-92 package.

For a 5V reference, the temperature is calculated as;

TC_10 = 2 * adval  + adval / 2 - 205; // 2.5 * adval - 205
TF_10 = 9 * TC_10 / 5 + 320;  // 1.8 * TC

A more complete explanation is at;

http://www.phanderson.com/PIC/PICC/sourceboost/mcp9701.html

********************

+5
|
MCP9701 -------------- AN0 (term 17)
|
GRD                                     TX (term8) ------ Serial LCD

Open on PORTB4 displays in degrees C.  GRD on PORTB4 displays in F.  Note that
the internal weak pullup resistors are used.

#endif

#case

#device PIC16F1827 ICD=TRUE

#include <defs_1827.h>
#include <string.h>

#rom 0x8007 = {0x09e4, 0x0003}  // Manual Section 4.0

#define TRUE 1
#define FALSE 0

#define MINUS 0
#define POSITIVE 1

#define SUCCESS 1
#define FAILURE 0

void display_float_1(long x);
void asynch_setup(void);
void ser_char(char ch);

void delay_10us(byte t);
void delay_ms(long t);
void delay_s(long t);

int main()
{

ANSELA = 0x01;  // AN0 on RA0 - terminal 17
ANSELB = 0x00;
OSCCON = 0x6b; // 4.0 MHz internal

WPUB = 0x10;
wpuen_ = 0;

asynch_setup();
delay_ms(10);

printf(ser_char, "?f");
delay_ms(25);

while(1)
{
TF_10 = 9 * TC_10 / 5 + 320;
if (portb4 == 0)
{
display_float_1(TF_10);
printf(ser_char, " degs F?n");
}
else
{
display_float_1(TC_10);
printf(ser_char, " degs C?n");
}
delay_s(30); // every 30 seconds
}
}

{
// A/D is discussed in Manual Section 15.
byte n;

// assume that ANSELA and ANSELH have been configured.  Manual Section 12.

ADCON0 = 0x01 | (channel << 2);
sum=0;
for (n=0; n < num_samples; n++)
{
go = 1;
while(go)
{ // wait for bit to go to zero
}

}
avg = sum / num_samples;
return(avg);
}

void display_float_1(long x)
{  // assumes x is positive
byte whole, fract;
whole = x/10;
fract = x%10;
printf(ser_char, "%d.%d", whole, fract);
}

void ser_char(char ch)
{
TXREG = ch;
while(trmt == 0) // wait for trmt to return to logic one
{
}
}

void asynch_setup(void)
{
txcksel = 0;    // assign TX to RB2
rxdtsel = 0;    // RX to RB1
trisb2 = 1;
trisb1 = 1;    // TX

spen = 1;     // enable serial port
sync = 0;     // asynchronous
txen = 1;     // enable transmitter

brgh = 1;
brg16 = 1;
SPBRGH = 0x00;
SPBRGL = 103; // 9600 at 4.0 MHz clock
}

void delay_s(long t)
{
while(t--)
{
delay_ms(1000);
}
}

void delay_ms(long t)   // delays t millisecs
{
do
{
delay_10us(100);
} while(--t);
}

void delay_10us(byte t)
{
#asm
//      BCF STATUS, RP0
DELAY_10US_1:
CLRWDT
NOP
NOP
NOP
NOP
NOP
NOP
DECFSZ t, F
GOTO DELAY_10US_1
#endasm
}
```