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

"fast polled" ADC

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







"fast polled" ADC
PostPosted: Tue Dec 03, 2002 5:12 am     Reply with quote

I have a polled loop (interrupts had too much overhead, affecting performance) to collect eight analog inputs and monitor eight digital inputs. Doing the set_adc_channel()/wait/read_adc() takes too long and I miss a number of digital events. The analog data collection can be spread over time, so I implemented as a state machine in the loop, executing a small section each pass. The big killers are read_adc() and delay_us(). I could spread the delay_us() via multiple loops of smaller delays, but don't know how to do the same for the read_adc(). Any suggestions on how to incrementally process the ADCs without dramatically increasing the poll loop time?

CCS 3.127
PIC18F452 @ 40Mhz

#device ADC=10
#fast_io(A)
#fast_io(D)
#priority ssp

#define ANALOG_MAX 8
#define COUNT_MAX 8

enum ANALOG_STATE {NEW_CONVERSION, WAIT_CONVERSION, READ_DATUM, NEXT_CONVERSION} a_state;

long analog[ANALOG_MAX];
long count[CHANNEL_MAX];
int counts;
int index;
int a_index = 0;

a_state = NEW_CONVERSION;

while (TRUE) {
switch(a_state)
{
case NEW_CONVERSION:
set_adc_channel(a_index);
a_state = WAIT_CONVERSION;
break;
case WAIT_CONVERSION:
delay_us(20);
a_state = READ_DATUM;
break;
case READ_DATUM:
analog[a_index] = read_adc();
a_state = NEXT_CONVERSION;
case NEXT_CONVERSION:
a_index++;
if (a_index>ANALOG_MAX)
a_index = 0;
a_state = NEW_CONVERSION;
break;
}

//
// Reading Port and Process bits
//
counts = input_d();
for (index=0; index count[index] += bit_test(counts, index);
}
}

The goal is to be able to sample port D around at 20KHz. Without the analog code, I can do this easily.

Once a second counts and analog values are read through a I2C port (via INT_SPP).

TIA...

R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9716
R.J.Hamlett
Guest







Re: "fast polled" ADC
PostPosted: Tue Dec 03, 2002 5:32 am     Reply with quote

:=
:=I have a polled loop (interrupts had too much overhead, affecting performance) to collect eight analog inputs and monitor eight digital inputs. Doing the set_adc_channel()/wait/read_adc() takes too long and I miss a number of digital events. The analog data collection can be spread over time, so I implemented as a state machine in the loop, executing a small section each pass. The big killers are read_adc() and delay_us(). I could spread the delay_us() via multiple loops of smaller delays, but don't know how to do the same for the read_adc(). Any suggestions on how to incrementally process the ADCs without dramatically increasing the poll loop time?
:=
:=CCS 3.127
:=PIC18F452 @ 40Mhz
:=
:=#device ADC=10
:=#fast_io(A)
:=#fast_io(D)
:=#priority ssp
:=
:=#define ANALOG_MAX 8
:=#define COUNT_MAX 8
:=
:=enum ANALOG_STATE {NEW_CONVERSION, WAIT_CONVERSION, READ_DATUM, NEXT_CONVERSION} a_state;
:=
:=long analog[ANALOG_MAX];
:=long count[CHANNEL_MAX];
:=int counts;
:=int index;
:=int a_index = 0;
:=
:=a_state = NEW_CONVERSION;
:=
:=while (TRUE) {
:= switch(a_state)
:= {
:= case NEW_CONVERSION:
:= set_adc_channel(a_index);
:= a_state = WAIT_CONVERSION;
:= break;
:= case WAIT_CONVERSION:
:= delay_us(20);
:= a_state = READ_DATUM;
:= break;
:= case READ_DATUM:
:= analog[a_index] = read_adc();
:= a_state = NEXT_CONVERSION;
:= case NEXT_CONVERSION:
:= a_index++;
:= if (a_index>ANALOG_MAX)
:= a_index = 0;
:= a_state = NEW_CONVERSION;
:= break;
:= }
:=
:= //
:= // Reading Port and Process bits
:= //
:= counts = input_d();
:= for (index=0; index := count[index] += bit_test(counts, index);
:= }
:=}
:=
:=The goal is to be able to sample port D around at 20KHz. Without the analog code, I can do this easily.
:=
:=Once a second counts and analog values are read through a I2C port (via INT_SPP).
:=
:=TIA...
:=
:= R
Do it manually like this:
#byte ADCON0=0xFC2
#byte ADCON1=0xFC1
#byte ADRESL=0xFC3
#byte ADRESH=0xFC4
#bit ADTRIG=0xFC2.2
//Use this if you want to enable/disable the converter
//to save power.
#bit ADON=0xFC2.0

#define ADSTART() (ADTRIG=1)
#define IS_AD_DONE() (ADTRIG==0)
#define READ_ADVAL() make16(ADRESH,ADRESL)

//You can then code as:

set_adc_channel(channel);
ADSTART();
//do anything you want here for the conversion time
//If you are unsure whether it has finished you can test with
if (IS_AD_DONE()) {
//Now you can read the actual value.
value=READ_ADVAL();
}

//Obviously if you are confident that the conversion time
//has allready passed, you don't have to test for
//'IS_AD_DONE', and can just read directly. Also you can
//include other code in the 'wait' as required. :-)

Best Wishes

___________________________
This message was ported from CCS's old forum
Original Post ID: 9717
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: "fast polled" ADC
PostPosted: Tue Dec 03, 2002 8:51 am     Reply with quote

:=
:=I have a polled loop (interrupts had too much overhead, affecting performance) to collect eight analog inputs and monitor eight digital inputs. Doing the set_adc_channel()/wait/read_adc() takes too long and I miss a number of digital events. The analog data collection can be spread over time, so I implemented as a state machine in the loop, executing a small section each pass. The big killers are read_adc() and delay_us(). I could spread the delay_us() via multiple loops of smaller delays, but don't know how to do the same for the read_adc(). Any suggestions on how to incrementally process the ADCs without dramatically increasing the poll loop time?

I had very nearly the same problem. You can look over my solution in another thread. I would recomend that you don't use the function read_ADC(), because it takes minimum 20 uS to process. Also try not to set the channel using a variable because that will decrease your scan rate. Hard code the variable. (set_adc_channel(2);)

<a href="http://www.pic-c.com/forum/general/posts/9217.html" TARGET="_blank">http://www.pic-c.com/forum/general/posts/9217.html</a>
___________________________
This message was ported from CCS's old forum
Original Post ID: 9728
rocco
Guest







Re: "fast polled" ADC
PostPosted: Tue Dec 03, 2002 1:01 pm     Reply with quote

:=:=
:=:=I have a polled loop (interrupts had too much overhead, affecting performance) to collect eight analog inputs and monitor eight digital inputs. Doing the set_adc_channel()/wait/read_adc() takes too long and I miss a number of digital events. The analog data collection can be spread over time, so I implemented as a state machine in the loop, executing a small section each pass. The big killers are read_adc() and delay_us(). I could spread the delay_us() via multiple loops of smaller delays, but don't know how to do the same for the read_adc(). Any suggestions on how to incrementally process the ADCs without dramatically increasing the poll loop time?
//
// snip..
//
:=Do it manually like this:
:=#byte ADCON0=0xFC2
:=#byte ADCON1=0xFC1
:=#byte ADRESL=0xFC3
:=#byte ADRESH=0xFC4
:=#bit ADTRIG=0xFC2.2
:=//Use this if you want to enable/disable the converter
:=//to save power.
:=#bit ADON=0xFC2.0
:=
:=#define ADSTART() (ADTRIG=1)
:=#define IS_AD_DONE() (ADTRIG==0)
:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=
:=//You can then code as:
:=
:= set_adc_channel(channel);
:= ADSTART();
:= //do anything you want here for the conversion time
:= //If you are unsure whether it has finished you can test with
:= if (IS_AD_DONE()) {
:= //Now you can read the actual value.
:= value=READ_ADVAL();
:= }
:=
:= //Obviously if you are confident that the conversion time
:= //has allready passed, you don't have to test for
:= //'IS_AD_DONE', and can just read directly. Also you can
:= //include other code in the 'wait' as required. :-)
:=
:=Best Wishes
:=

I made the changes you suggested below. Everything runs, but the values returned from READ_AVAL() are different from read_adc()... (read_adc() returns the expected values). Am I missing a critical step here?

Here is the manual version:
#byte ADCON0 = 0xFC2
#byte ADCON1 = 0xFC1
#byte ADRESL = 0xFC3
#byte ADRESH = 0xFC4

#bit ADON = ADCON0.0
#bit GO_DONE = ADCON0.2

#define ADSTART() (GO_DONE=1)
#define IS_AD_DONE() (GO_DONE==0)
#define READ_ADVAL() make16(ADRESH,ADRESL)

// Other Stuff...
long analog[ANALOG_MAX];
long *analog_ptr;

analog_ptr = analog;
a_state = NEW_CONVERSION;

while (TRUE) // Program Loop
{
// Analog Processing -
if (READ_DATUM == a_state) {
if (IS_AD_DONE()) { // Ready to process...
// *analog_ptr = READ_ADVAL();
*analog_ptr = read_adc();
a_state = NEXT_CHANNEL;
}
}
else if (NEXT_CHANNEL == a_state) {
++analog_index;
if (analog_index >= ANALOG_MAX) {// Reset to Begining..
analog_index = 0;
analog_ptr = analog;
}
else {
++analog_ptr;
}
a_state = NEW_CONVERSION;
}
else if (NEW_CONVERSION == a_state) {
set_adc_channel(analog_index);
ADSTART();
a_state = READ_DATUM;
}

// Do more useful stuff ... using cycles...
}

Thanks...

R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9735
rocco
Guest







Re: "fast polled" ADC
PostPosted: Tue Dec 03, 2002 2:17 pm     Reply with quote

:=
:=I had very nearly the same problem. You can look over my solution in another thread. I would recomend that you don't use the function read_ADC(), because it takes minimum 20 uS to process. Also try not to set the channel using a variable because that will decrease your scan rate. Hard code the variable. (set_adc_channel(2);)
:=
:= <a href="http://www.pic-c.com/forum/general/posts/9217.html" TARGET="_blank"> <a href="http://www.pic-c.com/forum/general/posts/9217.html" TARGET="_blank">http://www.pic-c.com/forum/general/posts/9217.html</a></a>

I have not much luck getting a replacement for the read_adc() {getting value directly from ADRESH & ADRESL. I separated the ADCON0.GO_DONE flag so it set in one pass of the loop (right after the set_adc_channel), then test the bit to see if it clears on each pass of the loop. read_adc() appears to do the same thing, but all in one call (thus adding more time)...

I looked at using hardcoded indexes, but I think in my case (scanning eight channels), the overhead of the if/else test kills any gains from the constant index.

.................... if (analog_index == 0)
0480: MOVF 44,F
0482: BTFSS FD8.2
0484: GOTO 0498
.................... set_adc_channel(0);
0488: MOVLW 00
048A: MOVWF 01
048C: MOVF FC2,W
048E: ANDLW C7
0490: IORWF 01,W
0492: MOVWF FC2
.................... else if (analog_index == 1)
0494: GOTO 0546
0498: DECFSZ 44,W
049A: GOTO 04AE
.................... set_adc_channel(1);
049E: MOVLW 08
04A0: MOVWF 01
04A2: MOVF FC2,W
04A4: ANDLW C7
04A6: IORWF 01,W
04A8: MOVWF FC2
.................... else if (analog_index == 2)

versus

.................... set_adc_channel(analog_index);
0546: RLCF 44,W
0548: MOVWF 00
054A: RLCF 00,F
054C: RLCF 00,F
054E: MOVLW F8
0550: ANDWF 00,F
0552: MOVF 00,W
0554: MOVWF 01
0556: MOVF FC2,W
0558: ANDLW C7
055A: IORWF 01,W
055C: MOVWF FC2

Getting closer.. just not close enough...

R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9739
R.J.Hamlett
Guest







Re: "fast polled" ADC
PostPosted: Tue Dec 03, 2002 4:57 pm     Reply with quote

:=:=:=
:=:=:=I have a polled loop (interrupts had too much overhead, affecting performance) to collect eight analog inputs and monitor eight digital inputs. Doing the set_adc_channel()/wait/read_adc() takes too long and I miss a number of digital events. The analog data collection can be spread over time, so I implemented as a state machine in the loop, executing a small section each pass. The big killers are read_adc() and delay_us(). I could spread the delay_us() via multiple loops of smaller delays, but don't know how to do the same for the read_adc(). Any suggestions on how to incrementally process the ADCs without dramatically increasing the poll loop time?
:=//
:=// snip..
:=//
:=:=Do it manually like this:
:=:=#byte ADCON0=0xFC2
:=:=#byte ADCON1=0xFC1
:=:=#byte ADRESL=0xFC3
:=:=#byte ADRESH=0xFC4
:=:=#bit ADTRIG=0xFC2.2
:=:=//Use this if you want to enable/disable the converter
:=:=//to save power.
:=:=#bit ADON=0xFC2.0
:=:=
:=:=#define ADSTART() (ADTRIG=1)
:=:=#define IS_AD_DONE() (ADTRIG==0)
:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=
:=:=//You can then code as:
:=:=
:=:= set_adc_channel(channel);
:=:= ADSTART();
:=:= //do anything you want here for the conversion time
:=:= //If you are unsure whether it has finished you can test with
:=:= if (IS_AD_DONE()) {
:=:= //Now you can read the actual value.
:=:= value=READ_ADVAL();
:=:= }
:=:=
:=:= //Obviously if you are confident that the conversion time
:=:= //has allready passed, you don't have to test for
:=:= //'IS_AD_DONE', and can just read directly. Also you can
:=:= //include other code in the 'wait' as required. :-)
:=:=
:=:=Best Wishes
:=:=
:=
:=I made the changes you suggested below. Everything runs, but the values returned from READ_AVAL() are different from read_adc()... (read_adc() returns the expected values). Am I missing a critical step here?
:=
No, I wrote it pretty fast, and 'off the cuff', so I've probably missed something. I have had problems (continuously...) with pointers being incorrectly sized in the CCS C, though this seems to be fixed in the newer versions, but this might cause a problem. Personally I'd stick to just storing the results directly into the array, as safer...
What sort of ratio of values are you getting?. If it is out by 64*, then the default setup is assuming left justified results, and you'd have to change this. If nothing is coming back, try enabling the AD (ADON=true), I thought this was done by default, but maybe it isn't.
Why are you doing a 'read_adc', after doing the 'READ_ADVAL'?. This throws away the advantage, since you will then re-execute the ADC fetch.

Best Wishes

:=Here is the manual version:
:=#byte ADCON0 = 0xFC2
:=#byte ADCON1 = 0xFC1
:=#byte ADRESL = 0xFC3
:=#byte ADRESH = 0xFC4
:=
:=#bit ADON = ADCON0.0
:=#bit GO_DONE = ADCON0.2
:=
:=#define ADSTART() (GO_DONE=1)
:=#define IS_AD_DONE() (GO_DONE==0)
:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=
:=// Other Stuff...
:=long analog[ANALOG_MAX];
:=long *analog_ptr;
:=
:= analog_ptr = analog;
:= a_state = NEW_CONVERSION;
:=
:= while (TRUE) // Program Loop
:= {
:= // Analog Processing -
:= if (READ_DATUM == a_state) {
:= if (IS_AD_DONE()) { // Ready to process...
:= // *analog_ptr = READ_ADVAL();
:= *analog_ptr = read_adc();
:= a_state = NEXT_CHANNEL;
:= }
:= }
:= else if (NEXT_CHANNEL == a_state) {
:= ++analog_index;
:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:= analog_index = 0;
:= analog_ptr = analog;
:= }
:= else {
:= ++analog_ptr;
:= }
:= a_state = NEW_CONVERSION;
:= }
:= else if (NEW_CONVERSION == a_state) {
:= set_adc_channel(analog_index);
:= ADSTART();
:= a_state = READ_DATUM;
:= }
:=
:= // Do more useful stuff ... using cycles...
:= }
:=
:=Thanks...
:=
:= R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9744
rocco
Guest







Re: "fast polled" ADC
PostPosted: Tue Dec 03, 2002 6:57 pm     Reply with quote

:=:=//
:=:=// snip..
:=:=//
:=:=:=Do it manually like this:
:=:=:=#byte ADCON0=0xFC2
:=:=:=#byte ADCON1=0xFC1
:=:=:=#byte ADRESL=0xFC3
:=:=:=#byte ADRESH=0xFC4
:=:=:=#bit ADTRIG=0xFC2.2
:=:=:=//Use this if you want to enable/disable the converter
:=:=:=//to save power.
:=:=:=#bit ADON=0xFC2.0
:=:=:=
:=:=:=#define ADSTART() (ADTRIG=1)
:=:=:=#define IS_AD_DONE() (ADTRIG==0)
:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=
:=:=:=//You can then code as:
:=:=:=
:=:=:= set_adc_channel(channel);
:=:=:= ADSTART();
:=:=:= //do anything you want here for the conversion time
:=:=:= //If you are unsure whether it has finished you can test with
:=:=:= if (IS_AD_DONE()) {
:=:=:= //Now you can read the actual value.
:=:=:= value=READ_ADVAL();
:=:=:= }
:=:=:=
:=:=:= //Obviously if you are confident that the conversion time
:=:=:= //has allready passed, you don't have to test for
:=:=:= //'IS_AD_DONE', and can just read directly. Also you can
:=:=:= //include other code in the 'wait' as required. :-)
:=:=:=
:=:=:=Best Wishes
:=:=:=
:=:=
:=:=I made the changes you suggested below. Everything runs, but the values returned from READ_AVAL() are different from read_adc()... (read_adc() returns the expected values). Am I missing a critical step here?
:=:=
:=No, I wrote it pretty fast, and 'off the cuff', so I've probably missed something. I have had problems (continuously...) with pointers being incorrectly sized in the CCS C, though this seems to be fixed in the newer versions, but this might cause a problem. Personally I'd stick to just storing the results directly into the array, as safer...
:=What sort of ratio of values are you getting?. If it is out by 64*, then the default setup is assuming left justified results, and you'd have to change this. If nothing is coming back, try enabling the AD (ADON=true), I thought this was done by default, but maybe it isn't.
:=Why are you doing a 'read_adc', after doing the 'READ_ADVAL'?. This throws away the advantage, since you will then re-execute the ADC fetch.
:=
:=Best Wishes
:=
:=:=Here is the manual version:
:=:=#byte ADCON0 = 0xFC2
:=:=#byte ADCON1 = 0xFC1
:=:=#byte ADRESL = 0xFC3
:=:=#byte ADRESH = 0xFC4
:=:=
:=:=#bit ADON = ADCON0.0
:=:=#bit GO_DONE = ADCON0.2
:=:=
:=:=#define ADSTART() (GO_DONE=1)
:=:=#define IS_AD_DONE() (GO_DONE==0)
:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=
:=:=// Other Stuff...
:=:=long analog[ANALOG_MAX];
:=:=long *analog_ptr;
:=:=
:=:= analog_ptr = analog;
:=:= a_state = NEW_CONVERSION;
:=:=
:=:= while (TRUE) // Program Loop
:=:= {
:=:= // Analog Processing -
:=:= if (READ_DATUM == a_state) {
:=:= if (IS_AD_DONE()) { // Ready to process...
:=:= // *analog_ptr = READ_ADVAL();
:=:= *analog_ptr = read_adc();
:=:= a_state = NEXT_CHANNEL;
:=:= }
:=:= }
:=:= else if (NEXT_CHANNEL == a_state) {
:=:= ++analog_index;
:=:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:=:= analog_index = 0;
:=:= analog_ptr = analog;
:=:= }
:=:= else {
:=:= ++analog_ptr;
:=:= }
:=:= a_state = NEW_CONVERSION;
:=:= }
:=:= else if (NEW_CONVERSION == a_state) {
:=:= set_adc_channel(analog_index);
:=:= ADSTART();
:=:= a_state = READ_DATUM;
:=:= }
:=:=
:=:= // Do more useful stuff ... using cycles...
:=:= }
:=:=
:=:=Thanks...
:=:=
:=:= R

I am getting values back, but not real obvious on why the difference. Here are four channel of analog data:
READ_ADVAL() read_adc()
0x0022 0x01E6
0x01FA 0x037F
0x0134 0x009F
0x00B4 0x01A7

Does not appear to be a nice shift or transpose (NOTE: the value varied a little due to the nature of the signal measured).

Regarding the "dual" calls of READ_ADVAL() & read_adc(). Simple debugging: I comment one out, then the other to compare performance and results (as above).

Actually it looks like my next hit is the SSP ISR for the slave I2C. When a I2C call comes in, I get a hit of ~1.5 ms. I don't know a clean way to reduce the time spent in the SSP ISR without cause other problems (overflows, clock stretching forever, ...).


Thanks,

R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9749
R.J.Hamlett
Guest







Re: "fast polled" ADC
PostPosted: Wed Dec 04, 2002 8:25 am     Reply with quote

:=
:=:=:=//
:=:=:=// snip..
:=:=:=//
:=:=:=:=Do it manually like this:
:=:=:=:=#byte ADCON0=0xFC2
:=:=:=:=#byte ADCON1=0xFC1
:=:=:=:=#byte ADRESL=0xFC3
:=:=:=:=#byte ADRESH=0xFC4
:=:=:=:=#bit ADTRIG=0xFC2.2
:=:=:=:=//Use this if you want to enable/disable the converter
:=:=:=:=//to save power.
:=:=:=:=#bit ADON=0xFC2.0
:=:=:=:=
:=:=:=:=#define ADSTART() (ADTRIG=1)
:=:=:=:=#define IS_AD_DONE() (ADTRIG==0)
:=:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=:=
:=:=:=:=//You can then code as:
:=:=:=:=
:=:=:=:= set_adc_channel(channel);
:=:=:=:= ADSTART();
:=:=:=:= //do anything you want here for the conversion time
:=:=:=:= //If you are unsure whether it has finished you can test with
:=:=:=:= if (IS_AD_DONE()) {
:=:=:=:= //Now you can read the actual value.
:=:=:=:= value=READ_ADVAL();
:=:=:=:= }
:=:=:=:=
:=:=:=:= //Obviously if you are confident that the conversion time
:=:=:=:= //has allready passed, you don't have to test for
:=:=:=:= //'IS_AD_DONE', and can just read directly. Also you can
:=:=:=:= //include other code in the 'wait' as required. :-)
:=:=:=:=
:=:=:=:=Best Wishes
:=:=:=:=
:=:=:=
:=:=:=I made the changes you suggested below. Everything runs, but the values returned from READ_AVAL() are different from read_adc()... (read_adc() returns the expected values). Am I missing a critical step here?
:=:=:=
:=:=No, I wrote it pretty fast, and 'off the cuff', so I've probably missed something. I have had problems (continuously...) with pointers being incorrectly sized in the CCS C, though this seems to be fixed in the newer versions, but this might cause a problem. Personally I'd stick to just storing the results directly into the array, as safer...
:=:=What sort of ratio of values are you getting?. If it is out by 64*, then the default setup is assuming left justified results, and you'd have to change this. If nothing is coming back, try enabling the AD (ADON=true), I thought this was done by default, but maybe it isn't.
:=:=Why are you doing a 'read_adc', after doing the 'READ_ADVAL'?. This throws away the advantage, since you will then re-execute the ADC fetch.
:=:=
:=:=Best Wishes
:=:=
:=:=:=Here is the manual version:
:=:=:=#byte ADCON0 = 0xFC2
:=:=:=#byte ADCON1 = 0xFC1
:=:=:=#byte ADRESL = 0xFC3
:=:=:=#byte ADRESH = 0xFC4
:=:=:=
:=:=:=#bit ADON = ADCON0.0
:=:=:=#bit GO_DONE = ADCON0.2
:=:=:=
:=:=:=#define ADSTART() (GO_DONE=1)
:=:=:=#define IS_AD_DONE() (GO_DONE==0)
:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=
:=:=:=// Other Stuff...
:=:=:=long analog[ANALOG_MAX];
:=:=:=long *analog_ptr;
:=:=:=
:=:=:= analog_ptr = analog;
:=:=:= a_state = NEW_CONVERSION;
:=:=:=
:=:=:= while (TRUE) // Program Loop
:=:=:= {
:=:=:= // Analog Processing -
:=:=:= if (READ_DATUM == a_state) {
:=:=:= if (IS_AD_DONE()) { // Ready to process...
:=:=:= // *analog_ptr = READ_ADVAL();
:=:=:= *analog_ptr = read_adc();
:=:=:= a_state = NEXT_CHANNEL;
:=:=:= }
:=:=:= }
:=:=:= else if (NEXT_CHANNEL == a_state) {
:=:=:= ++analog_index;
:=:=:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:=:=:= analog_index = 0;
:=:=:= analog_ptr = analog;
:=:=:= }
:=:=:= else {
:=:=:= ++analog_ptr;
:=:=:= }
:=:=:= a_state = NEW_CONVERSION;
:=:=:= }
:=:=:= else if (NEW_CONVERSION == a_state) {
:=:=:= set_adc_channel(analog_index);
:=:=:= ADSTART();
:=:=:= a_state = READ_DATUM;
:=:=:= }
:=:=:=
:=:=:= // Do more useful stuff ... using cycles...
:=:=:= }
:=:=:=
:=:=:=Thanks...
:=:=:=
:=:=:= R
:=
:=I am getting values back, but not real obvious on why the difference. Here are four channel of analog data:
:= READ_ADVAL() read_adc()
:= 0x0022 0x01E6
:= 0x01FA 0x037F
:= 0x0134 0x009F
:= 0x00B4 0x01A7
:=
:=Does not appear to be a nice shift or transpose (NOTE: the value varied a little due to the nature of the signal measured).
:=
:=Regarding the "dual" calls of READ_ADVAL() & read_adc(). Simple debugging: I comment one out, then the other to compare performance and results (as above).
:=
:=Actually it looks like my next hit is the SSP ISR for the slave I2C. When a I2C call comes in, I get a hit of ~1.5 ms. I don't know a clean way to reduce the time spent in the SSP ISR without cause other problems (overflows, clock stretching forever, ...).
:=
:=
:=Thanks,
:=
:= R
Looking at it again, I can see what is causing the problem.
There is the same requirement for the 'ADSTART' command, as normally applies with the 'read_adc' command, that there must be time allowed for the input capacitor to charge to the incoming voltage. This is a time of typically 20uSec, with a 10K ohm source impedance (less time is needed with a lower impedance). You are calling 'ADSTART', immediately after the set_adc_channel call, and so the capacitor has not fully charged. The error you see, will depend on the source impedance, and the difference in voltage value on the last source, and the new one. The timings 'split out' are:

select channel

delay to allow capacitor to charge (typically 20uSec)

start conversion

delay for conversion to complete (11Tad times for a 10bit conversion). 'Done' bit will be set when this is finished.

read data

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 9764
rocco
Guest







Re: "fast polled" ADC
PostPosted: Wed Dec 04, 2002 12:24 pm     Reply with quote

:=:=:=:=#byte ADCON0 = 0xFC2
:=:=:=:=#byte ADCON1 = 0xFC1
:=:=:=:=#byte ADRESL = 0xFC3
:=:=:=:=#byte ADRESH = 0xFC4
:=:=:=:=
:=:=:=:=#bit ADON = ADCON0.0
:=:=:=:=#bit GO_DONE = ADCON0.2
:=:=:=:=
:=:=:=:=#define ADSTART() (GO_DONE=1)
:=:=:=:=#define IS_AD_DONE() (GO_DONE==0)
:=:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=:=
:=:=:=:=// Other Stuff...
:=:=:=:=long analog[ANALOG_MAX];
:=:=:=:=long *analog_ptr;
:=:=:=:=
:=:=:=:= analog_ptr = analog;
:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=
:=:=:=:= while (TRUE) // Program Loop
:=:=:=:= {
:=:=:=:= // Analog Processing -
:=:=:=:= if (READ_DATUM == a_state) {
:=:=:=:= if (IS_AD_DONE()) { // Ready to process...
:=:=:=:= // *analog_ptr = READ_ADVAL();
:=:=:=:= *analog_ptr = read_adc();
:=:=:=:= a_state = NEXT_CHANNEL;
:=:=:=:= }
:=:=:=:= }
:=:=:=:= else if (NEXT_CHANNEL == a_state) {
:=:=:=:= ++analog_index;
:=:=:=:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:=:=:=:= analog_index = 0;
:=:=:=:= analog_ptr = analog;
:=:=:=:= }
:=:=:=:= else {
:=:=:=:= ++analog_ptr;
:=:=:=:= }
:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:= }
:=:=:=:= else if (NEW_CONVERSION == a_state) {
:=:=:=:= set_adc_channel(analog_index);
:=:=:=:= ADSTART();
:=:=:=:= a_state = READ_DATUM;
:=:=:=:= }
:=:=:=:=
:=:=:=:= // Do more useful stuff ... using cycles...
:=:=:=:= }
:=:=:=:=
:=:=:=:=Thanks...
:=:=:=:=
:=:=:=:= R
:=:=
:=:=I am getting values back, but not real obvious on why the difference. Here are four channel of analog data:
:=:= READ_ADVAL() read_adc()
:=:= 0x0022 0x01E6
:=:= 0x01FA 0x037F
:=:= 0x0134 0x009F
:=:= 0x00B4 0x01A7
:=:=
:=:=Does not appear to be a nice shift or transpose (NOTE: the value varied a little due to the nature of the signal measured).
:=:=
:=:=Regarding the "dual" calls of READ_ADVAL() & read_adc(). Simple debugging: I comment one out, then the other to compare performance and results (as above).
:=:=
:=:=Actually it looks like my next hit is the SSP ISR for the slave I2C. When a I2C call comes in, I get a hit of ~1.5 ms. I don't know a clean way to reduce the time spent in the SSP ISR without cause other problems (overflows, clock stretching forever, ...).
:=:=
:=:=
:=:=Thanks,
:=:=
:=:= R
:=Looking at it again, I can see what is causing the problem.
:=There is the same requirement for the 'ADSTART' command, as normally applies with the 'read_adc' command, that there must be time allowed for the input capacitor to charge to the incoming voltage. This is a time of typically 20uSec, with a 10K ohm source impedance (less time is needed with a lower impedance). You are calling 'ADSTART', immediately after the set_adc_channel call, and so the capacitor has not fully charged. The error you see, will depend on the source impedance, and the difference in voltage value on the last source, and the new one. The timings 'split out' are:
:=
:=select channel
:=
:=delay to allow capacitor to charge (typically 20uSec)
:=
:=start conversion
:=
:=delay for conversion to complete (11Tad times for a 10bit conversion). 'Done' bit will be set when this is finished.
:=
:=read data
:=
:=Best Wishes

That makes sense. Is there a "nice" way to know that the capacitor if sufficiently charged in a poll configuration? The GO_DONE bit test works pretty efficiently, but there does not appear to be a comparable bit for the "pre-charge." I would like to avoid putting delays in the code to assure that I have wanted long enough...

Thanks for the assistance...

R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9768
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: "fast polled" ADC
PostPosted: Wed Dec 04, 2002 1:47 pm     Reply with quote

:=
:=:=:=:=:=#byte ADCON0 = 0xFC2
:=:=:=:=:=#byte ADCON1 = 0xFC1
:=:=:=:=:=#byte ADRESL = 0xFC3
:=:=:=:=:=#byte ADRESH = 0xFC4
:=:=:=:=:=
:=:=:=:=:=#bit ADON = ADCON0.0
:=:=:=:=:=#bit GO_DONE = ADCON0.2
:=:=:=:=:=
:=:=:=:=:=#define ADSTART() (GO_DONE=1)
:=:=:=:=:=#define IS_AD_DONE() (GO_DONE==0)
:=:=:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=:=:=
:=:=:=:=:=// Other Stuff...
:=:=:=:=:=long analog[ANALOG_MAX];
:=:=:=:=:=long *analog_ptr;
:=:=:=:=:=
:=:=:=:=:= analog_ptr = analog;
:=:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=:=
:=:=:=:=:= while (TRUE) // Program Loop
:=:=:=:=:= {
:=:=:=:=:= // Analog Processing -
:=:=:=:=:= if (READ_DATUM == a_state) {
:=:=:=:=:= if (IS_AD_DONE()) { // Ready to process...
:=:=:=:=:= // *analog_ptr = READ_ADVAL();
:=:=:=:=:= *analog_ptr = read_adc();
:=:=:=:=:= a_state = NEXT_CHANNEL;
:=:=:=:=:= }
:=:=:=:=:= }
:=:=:=:=:= else if (NEXT_CHANNEL == a_state) {
:=:=:=:=:= ++analog_index;
:=:=:=:=:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:=:=:=:=:= analog_index = 0;
:=:=:=:=:= analog_ptr = analog;
:=:=:=:=:= }
:=:=:=:=:= else {
:=:=:=:=:= ++analog_ptr;
:=:=:=:=:= }
:=:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=:= }
:=:=:=:=:= else if (NEW_CONVERSION == a_state) {
:=:=:=:=:= set_adc_channel(analog_index);
:=:=:=:=:= ADSTART();
:=:=:=:=:= a_state = READ_DATUM;
:=:=:=:=:= }
:=:=:=:=:=
:=:=:=:=:= // Do more useful stuff ... using cycles...
:=:=:=:=:= }
:=:=:=:=:=
:=:=:=:=:=Thanks...
:=:=:=:=:=
:=:=:=:=:= R
:=:=:=
:=:=:=I am getting values back, but not real obvious on why the difference. Here are four channel of analog data:
:=:=:= READ_ADVAL() read_adc()
:=:=:= 0x0022 0x01E6
:=:=:= 0x01FA 0x037F
:=:=:= 0x0134 0x009F
:=:=:= 0x00B4 0x01A7
:=:=:=
:=:=:=Does not appear to be a nice shift or transpose (NOTE: the value varied a little due to the nature of the signal measured).
:=:=:=
:=:=:=Regarding the "dual" calls of READ_ADVAL() & read_adc(). Simple debugging: I comment one out, then the other to compare performance and results (as above).
:=:=:=
:=:=:=Actually it looks like my next hit is the SSP ISR for the slave I2C. When a I2C call comes in, I get a hit of ~1.5 ms. I don't know a clean way to reduce the time spent in the SSP ISR without cause other problems (overflows, clock stretching forever, ...).
:=:=:=
:=:=:=
:=:=:=Thanks,
:=:=:=
:=:=:= R
:=:=Looking at it again, I can see what is causing the problem.
:=:=There is the same requirement for the 'ADSTART' command, as normally applies with the 'read_adc' command, that there must be time allowed for the input capacitor to charge to the incoming voltage. This is a time of typically 20uSec, with a 10K ohm source impedance (less time is needed with a lower impedance). You are calling 'ADSTART', immediately after the set_adc_channel call, and so the capacitor has not fully charged. The error you see, will depend on the source impedance, and the difference in voltage value on the last source, and the new one. The timings 'split out' are:
:=:=
:=:=select channel
:=:=
:=:=delay to allow capacitor to charge (typically 20uSec)
:=:=
:=:=start conversion
:=:=
:=:=delay for conversion to complete (11Tad times for a 10bit conversion). 'Done' bit will be set when this is finished.
:=:=
:=:=read data
:=:=
:=:=Best Wishes
:=
:=That makes sense. Is there a "nice" way to know that the capacitor if sufficiently charged in a poll configuration? The GO_DONE bit test works pretty efficiently, but there does not appear to be a comparable bit for the "pre-charge." I would like to avoid putting delays in the code to assure that I have wanted long enough...
:=
:=Thanks for the assistance...
:=
:= R


How about this. Define the timer2 interupt flag as "tick". Do not enable timer2. Set the period for timer2 to be 40uS.

while(1)
{
process_digital_inputs(); //What ever you got to do for digital inputs
if(tick)
{tick = 0;
process_Analogs(); // switch channels, begin readings, read.
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 9773
rocco
Guest







Re: "fast polled" ADC
PostPosted: Wed Dec 04, 2002 3:06 pm     Reply with quote

:=:=
:=:=:=:=:=:=#byte ADCON0 = 0xFC2
:=:=:=:=:=:=#byte ADCON1 = 0xFC1
:=:=:=:=:=:=#byte ADRESL = 0xFC3
:=:=:=:=:=:=#byte ADRESH = 0xFC4
:=:=:=:=:=:=
:=:=:=:=:=:=#bit ADON = ADCON0.0
:=:=:=:=:=:=#bit GO_DONE = ADCON0.2
:=:=:=:=:=:=
:=:=:=:=:=:=#define ADSTART() (GO_DONE=1)
:=:=:=:=:=:=#define IS_AD_DONE() (GO_DONE==0)
:=:=:=:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=:=:=:=
:=:=:=:=:=:=// Other Stuff...
:=:=:=:=:=:=long analog[ANALOG_MAX];
:=:=:=:=:=:=long *analog_ptr;
:=:=:=:=:=:=
:=:=:=:=:=:= analog_ptr = analog;
:=:=:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=:=:=
:=:=:=:=:=:= while (TRUE) // Program Loop
:=:=:=:=:=:= {
:=:=:=:=:=:= // Analog Processing -
:=:=:=:=:=:= if (READ_DATUM == a_state) {
:=:=:=:=:=:= if (IS_AD_DONE()) { // Ready to process...
:=:=:=:=:=:= // *analog_ptr = READ_ADVAL();
:=:=:=:=:=:= *analog_ptr = read_adc();
:=:=:=:=:=:= a_state = NEXT_CHANNEL;
:=:=:=:=:=:= }
:=:=:=:=:=:= }
:=:=:=:=:=:= else if (NEXT_CHANNEL == a_state) {
:=:=:=:=:=:= ++analog_index;
:=:=:=:=:=:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:=:=:=:=:=:= analog_index = 0;
:=:=:=:=:=:= analog_ptr = analog;
:=:=:=:=:=:= }
:=:=:=:=:=:= else {
:=:=:=:=:=:= ++analog_ptr;
:=:=:=:=:=:= }
:=:=:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=:=:= }
:=:=:=:=:=:= else if (NEW_CONVERSION == a_state) {
:=:=:=:=:=:= set_adc_channel(analog_index);
:=:=:=:=:=:= ADSTART();
:=:=:=:=:=:= a_state = READ_DATUM;
:=:=:=:=:=:= }
:=:=:=:=:=:=
:=:=:=:=:=:= // Do more useful stuff ... using cycles...
:=:=:=:=:=:= }
:=:=:=:=:=:=
:=:=:=:=:=:=Thanks...
:=:=:=:=:=:=
:=:=:=:=:=:= R
:=:=:=:=
:=:=:=:=I am getting values back, but not real obvious on why the difference. Here are four channel of analog data:
:=:=:=:= READ_ADVAL() read_adc()
:=:=:=:= 0x0022 0x01E6
:=:=:=:= 0x01FA 0x037F
:=:=:=:= 0x0134 0x009F
:=:=:=:= 0x00B4 0x01A7
:=:=:=:=
:=:=:=:=Does not appear to be a nice shift or transpose (NOTE: the value varied a little due to the nature of the signal measured).
:=:=:=:=
:=:=:=:=Regarding the "dual" calls of READ_ADVAL() & read_adc(). Simple debugging: I comment one out, then the other to compare performance and results (as above).
:=:=:=:=
:=:=:=:=Actually it looks like my next hit is the SSP ISR for the slave I2C. When a I2C call comes in, I get a hit of ~1.5 ms. I don't know a clean way to reduce the time spent in the SSP ISR without cause other problems (overflows, clock stretching forever, ...).
:=:=:=:=
:=:=:=:=
:=:=:=:=Thanks,
:=:=:=:=
:=:=:=:= R
:=:=:=Looking at it again, I can see what is causing the problem.
:=:=:=There is the same requirement for the 'ADSTART' command, as normally applies with the 'read_adc' command, that there must be time allowed for the input capacitor to charge to the incoming voltage. This is a time of typically 20uSec, with a 10K ohm source impedance (less time is needed with a lower impedance). You are calling 'ADSTART', immediately after the set_adc_channel call, and so the capacitor has not fully charged. The error you see, will depend on the source impedance, and the difference in voltage value on the last source, and the new one. The timings 'split out' are:
:=:=:=
:=:=:=select channel
:=:=:=
:=:=:=delay to allow capacitor to charge (typically 20uSec)
:=:=:=
:=:=:=start conversion
:=:=:=
:=:=:=delay for conversion to complete (11Tad times for a 10bit conversion). 'Done' bit will be set when this is finished.
:=:=:=
:=:=:=read data
:=:=:=
:=:=:=Best Wishes
:=:=
:=:=That makes sense. Is there a "nice" way to know that the capacitor if sufficiently charged in a poll configuration? The GO_DONE bit test works pretty efficiently, but there does not appear to be a comparable bit for the "pre-charge." I would like to avoid putting delays in the code to assure that I have wanted long enough...
:=:=
:=:=Thanks for the assistance...
:=:=
:=:= R
:=
:=
:=How about this. Define the timer2 interupt flag as "tick". Do not enable timer2. Set the period for timer2 to be 40uS.
:=
:=while(1)
:={
:=process_digital_inputs(); //What ever you got to do for digital inputs
:=if(tick)
:= {tick = 0;
:= process_Analogs(); // switch channels, begin readings, read.
:= }
:=}

Nice touch. No additional overhead other than the test for the "tick."


Thnx

R
___________________________
This message was ported from CCS's old forum
Original Post ID: 9779
R.J.Hamlett
Guest







Re: "fast polled" ADC
PostPosted: Thu Dec 05, 2002 3:21 am     Reply with quote

:=
:=:=:=:=:=#byte ADCON0 = 0xFC2
:=:=:=:=:=#byte ADCON1 = 0xFC1
:=:=:=:=:=#byte ADRESL = 0xFC3
:=:=:=:=:=#byte ADRESH = 0xFC4
:=:=:=:=:=
:=:=:=:=:=#bit ADON = ADCON0.0
:=:=:=:=:=#bit GO_DONE = ADCON0.2
:=:=:=:=:=
:=:=:=:=:=#define ADSTART() (GO_DONE=1)
:=:=:=:=:=#define IS_AD_DONE() (GO_DONE==0)
:=:=:=:=:=#define READ_ADVAL() make16(ADRESH,ADRESL)
:=:=:=:=:=
:=:=:=:=:=// Other Stuff...
:=:=:=:=:=long analog[ANALOG_MAX];
:=:=:=:=:=long *analog_ptr;
:=:=:=:=:=
:=:=:=:=:= analog_ptr = analog;
:=:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=:=
:=:=:=:=:= while (TRUE) // Program Loop
:=:=:=:=:= {
:=:=:=:=:= // Analog Processing -
:=:=:=:=:= if (READ_DATUM == a_state) {
:=:=:=:=:= if (IS_AD_DONE()) { // Ready to process...
:=:=:=:=:= // *analog_ptr = READ_ADVAL();
:=:=:=:=:= *analog_ptr = read_adc();
:=:=:=:=:= a_state = NEXT_CHANNEL;
:=:=:=:=:= }
:=:=:=:=:= }
:=:=:=:=:= else if (NEXT_CHANNEL == a_state) {
:=:=:=:=:= ++analog_index;
:=:=:=:=:= if (analog_index >= ANALOG_MAX) {// Reset to Begining..
:=:=:=:=:= analog_index = 0;
:=:=:=:=:= analog_ptr = analog;
:=:=:=:=:= }
:=:=:=:=:= else {
:=:=:=:=:= ++analog_ptr;
:=:=:=:=:= }
:=:=:=:=:= a_state = NEW_CONVERSION;
:=:=:=:=:= }
:=:=:=:=:= else if (NEW_CONVERSION == a_state) {
:=:=:=:=:= set_adc_channel(analog_index);
:=:=:=:=:= ADSTART();
:=:=:=:=:= a_state = READ_DATUM;
:=:=:=:=:= }
:=:=:=:=:=
:=:=:=:=:= // Do more useful stuff ... using cycles...
:=:=:=:=:= }
:=:=:=:=:=
:=:=:=:=:=Thanks...
:=:=:=:=:=
:=:=:=:=:= R
:=:=:=
:=:=:=I am getting values back, but not real obvious on why the difference. Here are four channel of analog data:
:=:=:= READ_ADVAL() read_adc()
:=:=:= 0x0022 0x01E6
:=:=:= 0x01FA 0x037F
:=:=:= 0x0134 0x009F
:=:=:= 0x00B4 0x01A7
:=:=:=
:=:=:=Does not appear to be a nice shift or transpose (NOTE: the value varied a little due to the nature of the signal measured).
:=:=:=
:=:=:=Regarding the "dual" calls of READ_ADVAL() & read_adc(). Simple debugging: I comment one out, then the other to compare performance and results (as above).
:=:=:=
:=:=:=Actually it looks like my next hit is the SSP ISR for the slave I2C. When a I2C call comes in, I get a hit of ~1.5 ms. I don't know a clean way to reduce the time spent in the SSP ISR without cause other problems (overflows, clock stretching forever, ...).
:=:=:=
:=:=:=
:=:=:=Thanks,
:=:=:=
:=:=:= R
:=:=Looking at it again, I can see what is causing the problem.
:=:=There is the same requirement for the 'ADSTART' command, as normally applies with the 'read_adc' command, that there must be time allowed for the input capacitor to charge to the incoming voltage. This is a time of typically 20uSec, with a 10K ohm source impedance (less time is needed with a lower impedance). You are calling 'ADSTART', immediately after the set_adc_channel call, and so the capacitor has not fully charged. The error you see, will depend on the source impedance, and the difference in voltage value on the last source, and the new one. The timings 'split out' are:
:=:=
:=:=select channel
:=:=
:=:=delay to allow capacitor to charge (typically 20uSec)
:=:=
:=:=start conversion
:=:=
:=:=delay for conversion to complete (11Tad times for a 10bit conversion). 'Done' bit will be set when this is finished.
:=:=
:=:=read data
:=:=
:=:=Best Wishes
:=
:=That makes sense. Is there a "nice" way to know that the capacitor if sufficiently charged in a poll configuration? The GO_DONE bit test works pretty efficiently, but there does not appear to be a comparable bit for the "pre-charge." I would like to avoid putting delays in the code to assure that I have wanted long enough...
:=
:=Thanks for the assistance...
The use of the timer proposed by another poster is a nice way to go. It is worth adding a little 'coda' at this point.
Your 'test' code, using set_adc_channel, followed immediately by read_adc, will still have exactly the same problem. The reason for the difference, is that because of the way read_adc is written (this actually changes with some compiler versions, but I am referring to a 'modern' compiler here), adds about three more instructions, before the adc read is triggered. This is why it is giving a different result (since the capacitor has charged further), but _does not_ guarantee that the capacitor has fully charged. The chip has no way at all of knowing whether the input capacitor is charged, however you are running the AD. The time required is completely dependant on your external hardware, and also on how accurate the result needs to be (you can trigger a conversion before the capacitor has fully charged, if you accept that only the higher bits of the result will be correct). If you look in the examples, using the AD, you will find in each case, there is a delay between selecting the channel, and actually reading the port (ex_speed, is one of the most obvious - many just use other code to provide the delay). If you read the manual for the function 'set_adc_channel', you will find that it specifically says that you should wait before reading.
So the requirement is there in both 'polled' mode, and using CCS's code.
One think it is worth considering, before adding a timer as suggested, is that if you change your code, so that the 'set_adc_channel' function is called as soon as you have changed the channel number (hence include this function inside the and 'NEXT CHANNEL' state), then on the next loop round, when it executes the 'NEW CONVERSION' code, the channel will allready have been selected, and you can trigger the read straight away. Hence:

while (TRUE) // Program Loop
{
// Analog Processing -
if (READ_DATUM == a_state) {
if (IS_AD_DONE()) { // Ready to process...
*analog_ptr = READ_ADVAL();
a_state = NEXT_CHANNEL;
}
}
else if (NEXT_CHANNEL == a_state) {
++analog_index;
if (analog_index >= ANALOG_MAX) {// Reset to Begining..
analog_index = 0;
analog_ptr = analog;
}
else {
++analog_ptr;
}
set_adc_channel(analog_index);
a_state = NEW_CONVERSION;
}
else if (NEW_CONVERSION == a_state) {
//Here, since the channel has allready been
//selected, the 'loop time', will have allowed
//the voltage to settle. :-)
//You would have to look at the total time
//taken in the loop to see if it is enough, but
//I'd suspect it'd be reasonable.
ADSTART();
a_state = READ_DATUM;
}

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 9793
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