Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] HI-TECH LM35 On PIC16F877A TQFP HELP

Status
Not open for further replies.

oiyela

Junior Member level 3
Joined
Mar 7, 2012
Messages
30
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,554
HI,
i am currently trying to display a lm35 reading on my LCD. i am having problems using the ADC. I need to know what i should declare ADCON1 and ADCON0 and what ever i need to put in. i am bring in the volatage from the LM35 on RA1 and my Vref is on RA3 . I am using a pic16f877a TQFP. please help i am really confused
 

Hello oiyela. How are you?

Here is the complete code for pic16F876A.


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
68
69
70
71
72
73
74
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D4 at RC7_bit;
sbit LCD_D5 at RC6_bit;
sbit LCD_D6 at RC5_bit;
sbit LCD_D7 at RC4_bit;
 
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D4_Direction at TRISC7_bit;
sbit LCD_D5_Direction at TRISC6_bit;
sbit LCD_D6_Direction at TRISC5_bit;
sbit LCD_D7_Direction at TRISC4_bit;
// End LCD module connections
void read_adc(void);
void custchar(char x, char y);
unsigned int result;
float n;
int temp,rs;
char txt[7];
const char character[]={4,10,4,0,0,0,0,0}; //degree symbol
void main(void)
{
TRISA.RA0=1;
ADCON0=0b10000000;        // select Fosc/2
ADCON1=0b11000000;        // select left justify result. A/D port configuration 0
ADCON0.ADON=1;                // turn on the A2D conversion module
Delay_ms(300);
LCD_init();
Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off
        while(1){
          Delay_ms(30);
          read_adc();
          n=(result*4.883);
          n+=0.05;
          temp=n;
          n=(n-temp)*10;
          rs=n;
          InttoStr(temp,txt);
          Lcd_Out(2,3,txt);
          Lcd_chr(2,10,'.');
          Lcd_chr(2,11,rs+48);
          custchar(2,12);
          Lcd_chr(2,13,'C');
          Delay_ms(30);
         }
 
}
 
 
void read_adc(void)
{
unsigned short i;
unsigned long result_temp=0;
      for(i=2000;i>0;i-=1) //looping 2000 times for getting average value
      {
        ADCON0.GO = 1; //ADGO is the bit 2 of the ADCON0 register
        while(ADCON0.GO==1); //ADC start, ADGO=0 after finish ADC progress
        result=ADRESH;
        result=result<<8; //shift to left for 8 bit
        result=result|ADRESL; //10 bit result from ADC
        result_temp+=result;
      }
result = result_temp/2000; //getting average value
}
 
void custchar(char x, char y){
char i;
Lcd_Cmd(64);
for(i=0;i<=7;i++) Lcd_Chr_CP(character[i]);
Lcd_Cmd(_LCD_RETURN_HOME);
LCD_chr(x,y,0);
}



---------- Post added at 21:27 ---------- Previous post was at 21:24 ----------

mikroC Pro compiler
 

Hi papunblg,
Thanks so much for your reply. i am using hi-tech and some of the declarations are not recognized by the software. would it be possible to find out if you can get the HI-tech code for this. please help me.

Thanks
 

Refer Datasheet, one similar project is available at the following site

https://sites.google.com/site/coole...0/tutorial-list/temperature-monitoring-system

Project is based on PIC18F4550, hope this will help

---------- Post added at 21:53 ---------- Previous post was at 21:49 ----------

Code:
	ADCON0 = 0x91;
//Fosc/64 is Selected
//Channel-1 is Selected i.e RA1
//Analog-to-Digital Converter Module is Powered Up
       ADCON1 = 0xC1;

This is for PIC16F877A, this will help you,
By setting these, you can Configure RA1 as analog pin and RA3 as Vref+ Pin..
Hope This help
 

HI,
i am currently trying to display a lm35 reading on my LCD. i am having problems using the ADC. I need to know what i should declare ADCON1 and ADCON0 and what ever i need to put in. i am bring in the volatage from the LM35 on RA1 and my Vref is on RA3 . I am using a pic16f877a TQFP. please help i am really confused

:) You will get an idea how to set ADCON1 and ADCON0. Also to convert it for HI-tech code not difficult
 

Have a look at this code hope this will help,
It is written in Hi-Tech C Compiler for Temperature Measurement without any vref pin

Code:
#include<htc.h>
#include<string.h>
#include<stdio.h>

#define _XTAL_FREQ 20000000

#define LCD_DATA PORTB
#define RS PORTCbits.RC0
#define RW PORTCbits.RC1
#define EN PORTCbits.RC2
void lcdcmd(unsigned char value);
void lcddata(unsigned char value);
void lcdstr(unsigned char msg[]);
void adc_display(unsigned int adc_data);

void main()
{
	unsigned int adc_data,i;
	
	TRISB = 0x00;
	TRISC = 0x00;
	TRISAbits.TRISA0 = 1;	//Channel A0 as Input Port
	EN = 0;
	lcdcmd(0x38);
	__delay_ms(10);
	lcdcmd(0x0E);
	__delay_ms(10);
	lcdcmd(0x01);
	__delay_ms(10);
	lcdcmd(0x06);
	__delay_ms(10);
	lcdcmd(0x83);
	lcdstr("PIC16F877A");
	__delay_ms(100);
	lcdcmd(0xC5);
	lcdstr("Temp. Unit");
	lcdcmd(0x01);
	lcdcmd(0x83);
	lcdstr("booting.....");
	__delay_ms(100);
	i = 0;
	do
	{
		lcdcmd(0xC0+i);
		lcddata(0xFF);
		__delay_ms(100);
		if(i>10)
		{
			__delay_ms(300);
		}
		i++;
	}while(i<16);
	lcdcmd(0x01);
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
	while(1)
	{
		//__delay_ms(100);
		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over
		//adc_data_l = ADRESL & 0x00FF;
		adc_data = ADRESH & 0x00FF;
		adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;
		
		adc_display(adc_data/2);
	}
}
void lcdcmd(unsigned char value)
{
	LCD_DATA = value;
	RS = 0;
	RW = 0;
	EN = 1;
	__delay_ms(10);
	EN = 0;
}
void lcddata(unsigned char value)
{
	LCD_DATA = value;
	RS = 1;
	RW = 0;
	EN = 1;
	__delay_ms(10);
	EN = 0;
}
void lcdstr(unsigned char msg[])
{
	unsigned int i,len;	
	len = strlen(msg);
	for(i=0;i<len;i++)
	{	
		lcddata(msg[i]);
		__delay_ms(100);
	}
}
void adc_display(unsigned int adc_data)
{
	int hundreds, tens, ones;
	unsigned char buffer[16];
	ones = adc_data%10;
	adc_data = adc_data/10;
	tens = adc_data%10;
	hundreds = adc_data/10;
	sprintf(buffer," %d%d%d",hundreds,tens,ones);
	lcdcmd(0x01);
	lcdstr("Temperature");
	lcdcmd(0xC0);
	lcdstr(buffer);
}

Hope this helps
 

For sbit LCD_RS_Direction at TRISC2_bit; Write #define LCD_RS RC2

Delay function will be like __delay_us(40);

See the documentation

---------- Post added at 22:07 ---------- Previous post was at 22:06 ----------

See Arun Sharma's example
 

Hi, Thanks everyone for your help But Can You Also Tell Me What Header Files I Need To Use For This??
 

Hi, Thanks everyone for your help But Can You Also Tell Me What Header Files I Need To Use For This??

I had posted the code in thread #6 and also posted the link in thread #4

If you have read that properly you would never ask this question..

Have a look on that.
 

Hi,
Thanks once again. i have put in the code and made my alterations buy the LCD displays random letters.
I have RA1 connected to the LM35 and have my Vref at RA3. i also set ADCON0 and ADCON1 using the datasheet. i think it could be the way i set the LCD.

Here is my editted code given to me by Arun Sharma
Code:
#include<htc.h>
#include<string.h>
#include<stdio.h>

#define _XTAL_FREQ 8000000

#define LCD_DATA PORTD
#define RS PORTDbits.RD4
#define RW PORTDbits.RD6
#define EN PORTDbits.RD5
void lcdcmd(unsigned char value);
void lcddata(unsigned char value);
void lcdstr(unsigned char msg[]);
void adc_display(unsigned int adc_data);

void main()
{
	unsigned int adc_data,i;
	
	TRISD = 0x00;
	TRISAbits.TRISA1 = 1;	//Channel A1 as Input Port
	EN = 0;
	lcdcmd(0x38);
	__delay_ms(10);
	lcdcmd(0x0E);
	__delay_ms(10);
	lcdcmd(0x01);
	__delay_ms(10);
	lcdcmd(0x06);
	__delay_ms(10);
	lcdcmd(0x83);
	lcdstr("PIC16F877A");
	__delay_ms(100);
	lcdcmd(0xC5);
	lcdstr("Temp. Unit");
	lcdcmd(0x01);
	lcdcmd(0x83);
	lcdstr("booting.....");
	__delay_ms(100);
	i = 0;
	do
	{
		lcdcmd(0xC0+i);
		lcddata(0xFF);
		__delay_ms(100);
		if(i>10)
		{
			__delay_ms(300);
		}
		i++;
	}while(i<16);
	lcdcmd(0x01);
	ADCON0 = 0x48;
//Fosc/8 is Selected
//Channel-1 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0x81;
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
	while(1)
	{
		//__delay_ms(100);
		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over
		//adc_data_l = ADRESL & 0x00FF;
		adc_data = ADRESH & 0x00FF;
		adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;
		
		adc_display(adc_data/2);
	}
}
void lcdcmd(unsigned char value)
{
	LCD_DATA = value;
	RS = 0;
	RW = 0;
	EN = 1;
	__delay_ms(10);
	EN = 0;
}
void lcddata(unsigned char value)
{
	LCD_DATA = value;
	RS = 1;
	RW = 0;
	EN = 1;
	__delay_ms(10);
	EN = 0;
}
void lcdstr(unsigned char msg[])
{
	unsigned int i,len;	
	len = strlen(msg);
	for(i=0;i<len;i++)
	{	
		lcddata(msg[i]);
		__delay_ms(100);
	}
}
void adc_display(unsigned int adc_data)
{
	int hundreds, tens, ones;
	unsigned char buffer[16];
	ones = adc_data%10;
	adc_data = adc_data/10;
	tens = adc_data%10;
	hundreds = adc_data/10;
	sprintf(buffer," %d%d%d",hundreds,tens,ones);
	lcdcmd(0x01);
	lcdstr("Temperature");
	lcdcmd(0xC0);
	lcdstr(buffer);
}

i am thinking this could be due to a lack of masking for the port D data port?
 

#define LCD_DATA PORTD
#define RS PORTDbits.RD4
#define RW PORTDbits.RD6
#define EN PORTDbits.RD5

Its due to this,
Either you have to change your LCD Connections or have to use the LCD in 4-Bit mode,
Tell me what can you do..

Want to use LCD-in 4 bit mode, or can change your connections..
My personal Opinion is that you must change your connections and shift the Control Pins of LCD to some other Port

Hope this Helps
 

i cant change my LCD connections because i have already fabricated the board. i am using the LCD 4-bit mode. that is how my original connections was fabricated for.
i have RS connect to R4
RW connect to R6
EN connects to R5
Please can you check my code if the ADCON0 and ADCON1 registers are accurate. Also is it possible to remove the flashing messages and just have the temperature to show only without showing other messages like booting.... and all that.

Thanks
 


Code C - [expand]
1
2
3
4
5
6
7
void adc_display(unsigned int adc_data);
void main()
{
    unsigned int adc_data,i;
              --------------------
              --------------------------
}




Avoid same name for a function parameter and a variable whose scope is local to main unless you have real reason to do so

Make the following change

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
while(1)
    {
        //__delay_ms(100);
                                 adc_data=0; //<------------------------- 
        ADCON0bits.GO = 1;  //Start Conversion
        while(ADCON0bits.GO == 1);  //Wait Here Until Conversion Gets Over
        //adc_data_l = ADRESL & 0x00FF;
        adc_data = ADRESH & 0x00FF;
        adc_data = adc_data<<8;
        adc_data = adc_data | ADRESL;
        
        adc_display(adc_data/2);
    }







First chek with the following small code:-


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
main()
{
    unsigned int adc_data,i;
    
    //add delay of 250mS needed for LCD and ADC check datasheet for exact time. 250 for safe side checking
               //Place LCD initialization codes     
 
              adc_data=123;
             adc_display(adc_data);
while(1)
{
}
}


Use the above mentioned small main(), other functions remain same
If its OK, Run the full code.
If full code is not ok, check ADC part.
 
Last edited:

Hi guys please look at this code i have to read_adc

Code:
//Last Modified: 11 January 2012

#define _XTAL_FREQ 	8000000

int read_a2d(unsigned char channel);

int read_a2d(unsigned char channel)
{
ADCON0=0x48;					//Turn on A/D module
ADCON1=0x81;					//Right Justify
if(channel<=7) ADRESL=ADRESL|(0b00000001<<channel);
else ADRESH=ADRESH|(0b00000001<<(channel-8));
ADCON0=(ADCON0&0xC3)|(channel<<2);			//select analog input channel
__delay_ms(2);
GO=1;							//initiate conversion on the selected channel
while(GO==1) continue;					//wait until conversion done
return(256*ADRESH+ADRESL);
}

My results keep resulting in 0 so am guessing the adc isn't reading from the right port.
I am using AN1 for the analogue input for the LM35 and also using a Vref at RA3 . i am using a 8MHZ crystal on a pic16f877a

Please if you have experience with this can you check my code and see if it is correct?

Thanks
 

Hi guys please look at this code i have to read_adc

My results keep resulting in 0 so am guessing the adc isn't reading from the right port.
I am using AN1 for the analogue input for the LM35 and also using a Vref at RA3 . i am using a 8MHZ crystal on a pic16f877a

Please if you have experience with this can you check my code and see if it is correct?

So now you are sure that your display part is working. Great advancement!
Tell me one thing - "also using a Vref at RA3" - what do you mean by that? Are you using any connection to that pin? How? and exactly what is the voltage you are giving to that pin?

---------- Post added at 23:19 ---------- Previous post was at 23:14 ----------

It may please also be noted that it is standard practice to take average of multiple readings (say, 2000 readings, by the ADC)
 

i have a constant voltage connected to RA3 on the micro controller of 2.5V this is used for Vref to give a good accuracy for the ADC.

This is so confusing, i hope i solve this i have 2 more weeks left for this project.

Help
 

i have a constant voltage connected to RA3 on the micro controller of 2.5V this is used for Vref to give a good accuracy for the ADC.

This is so confusing, i hope i solve this i have 2 more weeks left for this project.

Help

Vref pins are not used for accuracy in that sense . Before going to solve your problem, read the following to understand what is this Vref:-

The maximum analog voltage you can give to your PIC (directly, without any divider) is 5V. So whatever analog signal you are trying to measure, make sure that the i/p volt to that pin should not exceed beyond 5V. If you want to measure voltage more than 5V, you should use resistor voltage divider network. The values of resistances required depends on the range of input voltage. For 5V your micro will produce 1024.

What does Vref do?

Suppose in your experiment, if you are sure that your input analog signal will always between 2.5 -5V, then you can fix the Vref to 2.5V , and use the entire 10-bit range to measure the voltage between 2.5 -5V. That means you will get reading 0 for i/p 2.5V, and 1024 for i/p 5V or more. This enhances the accuracy of analog measurements this way.

---------- Post added at 23:53 ---------- Previous post was at 23:34 ----------

In your case, at max tem. +150C the ADC will get 1500mV. That is 1.5Volt max.
 
Last edited:

Thanks so much for this.The PIC16F877A datasheet says Vref should be equal to or higher than 2.2 V to ensure 1 LSB accuracy of A/D conversion. The output voltage from the sensor is converted to a 10-bit digital number using the internal ADC of the PIC16F877A. Since the voltage to be measured by the ADC ranges from 0 to 1.0V (that corresponds to maximum temperature range, 100 °C), the ADC requires a lower reference voltage (instead of the supply voltage Vdd = 5V) for A/D conversion in order to get better accuracy.
 

Synthesizing, we can reduce the different possibilities to obtain a reference supply voltage to the following:

1. using the 5V regulated power supply voltage, normally obtained by the use of a positive voltage regulator (7805 precision 4%, according to datasheets)
2. using dedicated components as micropower voltage reference diodes, as the LM385 for instance (a 1.235V or 2.5V zener diode, 1% precision).

Hope you are using a zener diode to supply Vref pin. Commonly done by us a simple 2.5 volt 500mW zener.

If the Vref+ has been set to 2.5V mV the conversion is: ADC_read_value = 2500/1024 = 2,441 (mV/step).

The LM35 provides 10mv/degree therefore the conversion will be very simply: ADC_read value * (2,441*1000 to avoid float point math) /1000*10(mV/degree).
 

Yes i am using a MCP1525 IC to generate a precise 2.5 V reference for A/D conversion. Thanks for the calculation i have noted that down. the issue now is to get the ADC_read value using HI-TECH code.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top