View previous topic :: View next topic |
Author |
Message |
tripper269
Joined: 06 May 2013 Posts: 33 Location: Toronto
|
using 0.6V adc channel |
Posted: Fri May 24, 2013 2:08 pm |
|
|
Hi there,
Anybody knows how to setup 0.6V or 1.2V channels for PIC12F615 ?
I want to compare this channel with Vdd so i can detect Vdd.
I am using below syntax:
Code: |
int sum =0;
setup_ADC_ports(VREF_6th | VS);
setup_adc(ADC_CLOCK_DIV_2);
while(1)
{
sum =read_adc();
|
but i am having random value in sum.
Any suggestions... |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri May 24, 2013 6:01 pm |
|
|
your syntax is messed up, as is the program concept.
as is the header file from CCS does not make your ADC mux setup
too EZ
to fix it -
FIRST setup_vref() for the ref value you want
then
1-read the header file for the part - get the right setup arguments
2- make the adc conversion reference be Vdd
3- select and read the 1.2v reference by:
A) try ->> set_adc_channel(6)
and if this fails
B) manipulating adcon0 to set input #6
( see datasheet - as CCS header no good for this in 4.141)
4- do the math ....
so....
you want to know if 5V is vdd ??
then...
if Vdd is ACTUALLY only 2.4 volts -
you would read 511 from the adc
if Vdd was 4.8 what would you expect from the ADC ?
and so on
also consider this factoid for the part ..
AD06
VREF Reference Voltage(3) 2.2/2.5 — —VDD
Absolute Vref (when Vdd)minimum to ensure 1 LSb
got the idea ??
![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Sat May 25, 2013 1:44 am |
|
|
It is always important/vital to read the header file.
The constant being used (VREF_6th), comes from the CCS section that reads:
Code: |
// Constants used in setup_vref() are:
//
#define VREF_LOW 0xA0
#define VREF_HIGH 0x80
#define VREF_6th 0x10 // Turn on .6V ref
// Or (with |) the above with a number 0-15
|
So, first note that this is for the setup_vref function _not_ the setup_adc_ports function. If you look at the Vref module, you then (hopefully) realise that this is to configure the Vref for it's design purpose (feeding the comparator), and allows you to select the '16 level; voltage range' (hence the number), and to select Vref high range, Vref low range, or the fixed 0.6v reference. The only point where this applies, is the comment "Turn on .6V ref". This sets the FVREN bit, which turns this reference 'on'.
You can never use constants for one defined function in another function, without unexpected results. It's like trying to use a timer setup to control the ADC. Duh.....
Now if you look at the ADC in the data sheet, you will find that the connection into the multiplexer, is permanent. Hence CCS's lack of a function to enable it. The Vref, is not used as a 'reference', but as an input. So is not selected using setup_adc_ports.
The internal Vref, is nothing to do with the ADC Vref. It is an internal source that can be read by the ADC, but the ADC Vref needs to come from somewhere else (AD06, therefore doesn't apply to this voltage).
So:
Code: |
setup_vref(VREF_6th);
//Turn _on_ the FVREN bit.
setup_adc_ports(NO_ANALOGS,VSS_VDD);
//disable external ADC pins, but set the ADC to use the supply
//as it's reference
setup_adc(ADC_CLOCK_DIV_16);
//assuming you are running the internal 4Mhz or 8MHz clock
//DIV_2 is not legal unless you are running at 1MHz or below.
set_adc_channel(6);
//select to read the 1.2v reference as an input
|
Now asmboy has given the 'thinking' you then have to follow to determine the Vdd from the reading. However remember this is not terribly accurate. The internal Vref is specified as 1.05 to 1.35v. A supply at 4.8v, could give readings between 224 and 288 depending on your chip (assuming you have ADC=10 selected). It is _not_ a precision reference. OK if you want to 'roughly know' when the supply is perhaps 25% below what it should be, but not if you want any sort of accuracy....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
tripper269
Joined: 06 May 2013 Posts: 33 Location: Toronto
|
|
Posted: Thu Jun 20, 2013 7:10 am |
|
|
Thanks to everybody for providing solutions. I think the problem is the CCS compiler itself. Its hard to play with the registers in CCS.
I completed it with MikroC in few minutes. Here is the code
Code: |
void main()
{
int sum = 0;
TRISIO = 0;
GPIO = 0;
ADCON0 = 0b00011001;
while(1)
{
sum = ADC_Read(6);
if (sum > 316)
GPIO.B5 = 1;
GPIO.B5 = 0;
}
}
|
I will appreciate if someone convert it in CCS.
Thanks |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Jun 20, 2013 10:14 am |
|
|
Quote: |
Its hard to play with the registers in CCS.
|
a MOST puzzling comment - as I have found it trivially EASY
with CCS - and so often not even necessary, given the
flexibility, quantity and quality of
CCS pre-defined hardware/register access functions provided.
In your posted code, there are excellent CCS functions that obviate the
register defines you use in 'mikroc'. you need only read the CCS manual
and you will see. No need to manipulate ADCON or define IO registers, set tris etc.
i suspect your sentiment may come from simply not having studied the
CCS manuals. |
|
![](templates/subSilver/images/spacer.gif) |
|