CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Internal reference using for adc?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
omid_juve



Joined: 25 Oct 2012
Posts: 8

View user's profile Send private message

Internal reference using for adc?
PostPosted: Thu Oct 25, 2012 1:35 am     Reply with quote

I am becoming so confused why my code is not working. I want to use internal vref 2.048v as a reference for my adc conversion but it doesn't work.
Please see my setup to see if it is correct.
Code:

#int_AD
 void AD_isr()
{

 value[0] = Read_ADC(ADC_READ_ONLY);
}


void main()
{
setup_vref(VREF_ON|VREF_ADC_2v048);
setup_adc_ports(sAN0|VSS_FVR);
setup_adc(ADC_CLOCK_DIV_64);
set_adc_channel( 0 );
Read_ADC(ADC_START_ONLY);
enable_interrupts(INT_AD);
enable_interrupts(GLOBAL);
}

When I put 2.5v on AN0 input channel it reads 511 !!!!!
plz help me.
My pic is 16f1947 Sad
Ttelmah



Joined: 11 Mar 2010
Posts: 19448

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 2:01 am     Reply with quote

First thing, don't use INT_AD. INT_AD, is only wanted, when you have something else triggering the ADC (CCP for example), or you use sleep for the conversion (it will then allow you to wake). Otherwise it takes longer to get into the interrupt than it would take to just wait for the conversion.....

What compiler?. Then we can check if the version you have does set this up correctly.

Obvious comment Tad. You _must_ always wait for Tad, between selecting an ADC channel, and reading it, or the value you get will be wrong. This may be your main problem. Internally the ADC has a small 'hold' capacitor, and this takes time to charge.

Best Wishes
omid_juve



Joined: 25 Oct 2012
Posts: 8

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 4:47 am     Reply with quote

Ttelmah wrote:
First thing, don't use INT_AD. INT_AD, is only wanted, when you have something else triggering the ADC (CCP for example), or you use sleep for the conversion (it will then allow you to wake). Otherwise it takes longer to get into the interrupt than it would take to just wait for the conversion.....

What compiler?. Then we can check if the version you have does set this up correctly.

Obvious comment Tad. You _must_ always wait for Tad, between selecting an ADC channel, and reading it, or the value you get will be wrong. This may be your main problem. Internally the ADC has a small 'hold' capacitor, and this takes time to charge.

Best Wishes


I use delay but the problem is still exist.
Please see the code.
Code:

#int_AD
 void AD_isr()
{
value[0] = Read_ADC(ADC_READ_ONLY);
delay_ms(1);
Read_ADC(ADC_START_ONLY);
}


void main()
{
setup_vref(VREF_ON|VREF_ADC_2v048);
setup_adc_ports(sAN0|VSS_FVR);
setup_adc(ADC_CLOCK_DIV_64);
set_adc_channel( 0 );
Read_ADC(ADC_START_ONLY);
enable_interrupts(INT_AD);
enable_interrupts(GLOBAL);
}

What do you mean by ""First thing, don't use INT_AD. INT_AD, is only wanted,""
Also my compiler version is 4.13 pcm
Ttelmah



Joined: 11 Mar 2010
Posts: 19448

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 7:28 am     Reply with quote

Code:

void main(void) {
   unsigned int16 value;
   setup_vref(VREF_ON|VREF_ADC_2v048);
   setup_adc_ports(sAN0|VSS_FVR);
   setup_adc(ADC_CLOCK_DIV_64);
   set_adc_channel( 0 ); 
   do {
      //This is where the delay is needed to allow the ADC to acquire
      delay_us(500);
      //Only needs to typically be 2.5 to 10uSec, but put longer
      //delay here to slow the output
      value=read_adc(); //Using INT_AD, _just costs time_
      printf("ADC value = %04lu\n\r",value);
   } while (TRUE);   
}

INT_AD, gains you absolutely nothing. It should _only_ be used, if you are either starting the ADC with a timer (in which case it triggers to tell you the conversion has happened), or if you are putting the processor to sleep for the ADC conversion. Otherwise all it does is _costs time_.

The delay needs to be between selecting the ADC channel, and performing the conversion, and between successive conversions _read the data sheet_.
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 8:58 am     Reply with quote

I have not looked at the spec sheet for your chip (not all chips have internal Vref sources you can use) - the one I was using is the 18f14k22 and when I was working on it last year, I found the compiler at that time did not correctly let me set the Vref to the internal bandgap reference. I ended up setting the config register myself - here is a snippet of code from my code showing how I did it - this may be what you have to do (I have not yet tried the new version of the compiler to see if it now understands the internal reference settings (I did notifiy CCS about the issue) - note that the page numbers referenced in the comments are for my chip the 18f14k22 (for my project, 1024 was full scale from the temp sensors).

Code:

   // Processor specific ADC config info
   // Define some SFR registers we need access to ...
#BYTE VREFCON0 = 0xFBA  // Vref configuration registers
#BYTE VREFCON1 = 0xFBB
#BYTE VREFCON2 = 0xFBC

#BYTE ADCON0 = 0xFC2    // A/D converter config registers
#BYTE ADCON1 = 0xFC1
#BYTE ADCON2 = 0xFC0
#define VSS_VFVR  0x800 // new definition to use internal vref not listed in .h

#BYTE ANSEL  = 0xF7E    // Analog Select Registers
#BYTE ANSELH = 0xF7F

#BYTE OSCCON = 0xFD3    // Oscillator control register
#BYTE OSCCON2= 0xFD2
.
.
.
setup_adc(ADC_CLOCK_DIV_16);
         
     // Have to enable the internal FVR and set to 1x
VREFCON0 = 0x90; // FVR enabled, 1x (1.024v)  (pg 245)
         
     //  VREFCON1 = 0x00; // DAC is disabled  (pg 246)
     //  VREFCON2 = 0x00; // DAC output disabled (pg 246)
     //  ADCON1   = 0x08; // pos vref from FVR, neg vref from Vss (pg 214,207)
     //  ADCON2   = 0x95; // Rt. justify, TAD4,Fosc/16   (pg 215)
 
     // setup_adc_ports(AIR_PORT | HTR_PORT); 
     // AN2 (RA2) = ambient temp, AN10 (RA10)=htr temp

_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
Ttelmah



Joined: 11 Mar 2010
Posts: 19448

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 9:14 am     Reply with quote

The 1947, does have this ability, but that is why I asked the compiler version. Like many such features, CCS tend to get them 'wrong' for the first few releases. It does appear to set the bits correctly with the current compiler.

Best Wishes
omid_juve



Joined: 25 Oct 2012
Posts: 8

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 1:02 pm     Reply with quote

Thanks to all of you that help me.
Finally I made it.
See the code below for your ref.
Code:

#byte fvrcon=0x117
fvrcon=0b10000010;
setup_adc_ports(sAN0|sAN1|sAN2|sAN3|sAN4,VSS_FVR,);
Ttelmah



Joined: 11 Mar 2010
Posts: 19448

View user's profile Send private message

PostPosted: Fri Oct 26, 2012 4:07 am     Reply with quote

Also, for _your_ reference, you have never answered the question asked right at the start - 'what compiler version'.
On 4.137, the compiler line:
Code:

setup_vref(VREF_ON|VREF_ADC_2v048);

Generates:
Code:

0015:  MOVLB  01
0016:  MOVLW  82
0017:  MOVWF  17


Which is putting 0x82, into address 117, which is what you are doing....

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group