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.

ADC with pic-not able to get desired output

Status
Not open for further replies.

Ram Prasadh

Member level 2
Joined
Feb 16, 2011
Messages
51
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Activity points
1,725
Hi friends,
I am using adc module in pic18f4550. I just gave a dc signal to the module and varied it with a pot. My ADRES register shows some value,but that is not the one I am expecting.I am not knownig where I am going wrong. I ave just copied my code below.

Code:
#include<htc.h>
void interrupt isr(void);
void main()
{
	
	TRISA = 0XFF;    TRISD = 0X00;
	PORTD = 0X00;   PORTA = 0X00;
	ADCON0 = 0x09;  ADCON1 = 0x0E; // Channel AN0 selected
	ADCON2 = 0X3E;
	T1CON = 0X00;
	PEIE = 1;  TMR1IE = 1;  GIE = 1;
	TMR1H=0XFF;   TMR1L=0XF7;   TMR1IF = 0;
	TMR1ON = 1;	
	while(1);
}
void interrupt isr(void)
{
	TMR1IF = 0;
	GO = 1;
	
	while(ADIF == 0);
	ADIF = 0;
	
	TMR1H=0XEF;
        TMR1L=0XE5;
	
	}

suppose if I set 5v dc as my input , I am expecting the value 3FF(10 bit value) on the ADRES register. I am not getting it. It displays some other value.Please help me with what i have missed out.will provide further information if something is left out.

Regards,
Ram
 
Last edited by a moderator:

what are your values when you apply 5v?

I am just getting 7FC0 on ADRES register when I give 5v dc into it. It gets reduced when i reduce the input here, but thats not the right value. I must get only 03FF for 5v and should get reduced subsequently.
 

You have to be careful about a number of parameters for the ADC to give the correct result
1. The ADC conversion clock.
2. The ADC aqusition time.
3. Table 21-1 on page-265 of the data sheet gives the correct combination for the device frequency and ADC clock prescaler.
3. Another important point is the way you read the ADC result registers.

Kindly post the complete code and the device frequency you are using and we will be in a better position to help you.
Regards.
 

HI...
check your reference voltage.
If your input to be measured is max 5v , then the ref vtg has to be 5 so as to get a value of 3FF.
Also take into consideration what other fellow members are saying about reading the adc data.It cannot be read before the conversion is over.
By the way I dont find any statement in the posted code where u are actually reading the ADC data.

cheers,
Vijay
 

I don't see ADRES being used in the code.
I am using pickit3 debugger. I think it is enough if I can view the ADRES register in the watch window in mplab.

where are u extracting the result of adc ............
after this line "while(ADIF == 0)" i am seeing in Watch window,ADRES register.
Kindly post the complete code and the device frequency you are using and we will be in a better position to help you.

I have a 20Mhz oscillator.
I have given the code again with some changes in the sampling frequency setting in ADCON2 register
Code:
#include<htc.h>
void interrupt isr(void);
void main()
{
	
	TRISA = 0XFF;    TRISD = 0X00;
	PORTD = 0X00;   PORTA = 0X00;
	ADCON0 = 0x01;  ADCON1 = 0x0E; // Channel AN0 selected
	ADCON2 = 0X3E;   //Fosc/64 with time delay of 20*Tad
	T1CON = 0X00;
	PEIE = 1;  TMR1IE = 1;  GIE = 1;
	TMR1H=0XFF;   TMR1L=0XF7;   TMR1IF = 0;
	TMR1ON = 1;	
	while(1);
}
void interrupt isr(void)
{
	TMR1IF = 0;
	GO = 1;
	
	while(ADIF == 0);
	ADIF = 0;
	
	TMR1H=0XEF;
        TMR1L=0XE5;
	
	}

I am not able to find where I am going wrong.
I need to just get a value corresponding to the input I give through pot.
On part of hardware , I think there wont be any mistake,that board is from a 3rd party vendor only.

I have given Fosc/64.. Is it right??

Regards
Ram
 

Is your ADCON0, ADCON1, and ADCON2 settings OK?

Here in this setting ADCON0 = 0x01; you are turning ADC by making ADON = 1;

You have to make ADCON0 = 0x00; during settings and then before sampling the adc ADON should be turned ON.

What is the purpose of timer?
 
Last edited:

Is your ADCON0, ADCON1, and ADCON2 settings OK?

adcon0 tells that i have selected channel 0 and and the last bit in adcon0 is the ADON.
adcon1 , i have configured all ports as digital except AN0 where I am providing the input.
adcon2 ,the Acquisition Time is 20*Tad and the Conversion Clock is ADCS2:ADCS0=110 ( FOSC/64).

My oscillator frequency is 20Mhz. Am i setting it right for this Fosc??



You have to make ADCON0 = 0x00; during settings and then before sampling the adc ADON should be turned ON.
What is the purpose of timer?

Ok , I will try that and see. I am basically trying FIR filter in this. That timer will act as sampling time.

- - - Updated - - -

check your reference voltage.
If your input to be measured is max 5v , then the ref vtg has to be 5 so as to get a value of 3FF.
Also take into consideration what other fellow members are saying about reading the adc data.It cannot be read before the conversion is over.
By the way I dont find any statement in the posted code where u are actually reading the ADC data.

I have configured such that my reference is always 5v. I am waiting until the ADIF gets set,
Code:
while(ADIF == 0);
. Is it not enough to be sure that the conversion has been completed? I am using Pickit 3 , so I can see the result in the watch window itself.
 
Last edited:

You should not put statements like while(ADIF == 0); in interrupt service routines. The interrupt has to be serviced as quick as possible.
 

You should not put statements like while(ADIF == 0); in interrupt service routines. The interrupt has to be serviced as quick as possible.

I am not using adc interrupt. The adif is polled inside the timer generated interrupt.If I am not using adc interrupt also , this adif flag is going to be set once the conversion is done.. So I am just polling that. Anyway this polling is going to take hardly 11 to 12 clock cycles only. Just polling an other thing inside a interrupt. That is all. But I dont know where am going wrong.:???:
 

Let us assume that an interrpt has occured due to yout timer. Then while(ADIF == 0); will be executed infinitely if ADIF is 0 i.e., if conversion is not complete.
Also while interrupt is being serviced will the ADC conversion completes and set ADIF to 1?
 

My input is always going to be a sinewave. Any input coming inside, it is going to make the conversion right?,let it be 0 0r 255 or any value. and moreover i cannot give two interrupts at the same time here right?? I need the timer because my conversion should take place only at specified time intervals. So timer interrupt is necessary.
Also while interrupt is being serviced will the ADC conversion completes and set ADIF to 1?

Yes , for sure it will do.Please correct me if I am wrong in anything specified above. I cannot take the timer interrupt out,as I said I am implementing fir filter,so this timer is going to act as my sampling time.
 

It seems that you see the result on ADRES shifted left by several bits. If the conversion is not complete when you try to read the register you may get this kind of results. You need to monitor the flag bit that indicates data is ready to be read. If that doesn't fix it for some reason you could try shifting the result to the right using the >> operator.
 

I dont know whether ADIF will be set if there is timer interrupt code is running. I think that when timer interrupt is being serviced all other code execution will be halted. So if ADIF is not set to 1, then when timer interrupt occurs then your code will be looping in while(ADIF == 0) and will never come out.

If you have a Proteus file zip and post it. Send me the .cof file I will debug and see.

Have you pulled the MCLR pin to Vcc using a 10k resistor? Where are your config settings in the code?
 
Last edited:

It seems that you see the result on ADRES shifted left by several bits. If the conversion is not complete when you try to read the register you may get this kind of results. You need to monitor the flag bit that indicates data is ready to be read. If that doesn't fix it for some reason you could try shifting the result to the right using the >> operator.

Are you coming to say that It is not only enough to see whether the ADIF has gone high? Should I check the DONE bit instead of the ADIF bit? so the code must probably be like
Code:
while(DONE);
...Right? By default , my value 9:3 should reside in the ADRESH and 2:0 in the ADRESL. Why should I do the shifting.??
 

Your code should be something like this.

Code:
ADCON0bits.GO = 1;
while(ADCON0bits.GO);
ADCON0bits.ADON = 0;

Can you post yout hex and cof files? Check my last post it is updated.
 

As an experiment read the value of adc on an adc interrupt instead of timer interrupt. I think that with the reload values that you are using in the last code you are not giving enough time for the result to convert.
 

Waseem is right. What is the duration of each interrupt caused due to timer?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top