|
|
View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 354
|
ADC-MCP342x |
Posted: Fri Apr 03, 2015 3:09 am |
|
|
Hello !
I have used "CCS MCP432x.c" ADC driver and I have the following problem:
In the code of driver have the following section Code: |
do
{
status = i2c_read(MCP342X_STREAM, 1); //read Status
} while(bit_test(status, 7)); //until RDY = 0
| Which significantly slows down the cycle of my program.
I tried to replace "while(..)" with other operator but it is not refreshing ADC value.
How can I solve this problem?
Thanks for attention! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Fri Apr 03, 2015 3:35 am |
|
|
Do something else while you are waiting....
You have to wait.
It is waiting for the chip to signal back that it has completed.
What you can do though, is do another job inside the loop, provided it has nothing to do with the ADC, to 'use the time', till the ADC signals it is ready. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Fri Apr 03, 2015 3:57 am |
|
|
It is not a good idea, because it is another compilation unit included in main project. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Apr 03, 2015 7:44 am |
|
|
Mr. T gave you good advice. \
you don't say which precise part you are using , but
If there is a sequential time dependent aspect to your program
you have no choice but to make it a part of main() .
or pick another part that offers the resolution you need
AND is faster than a slow poke delta-sigma design of this low end converter family. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Fri Apr 03, 2015 8:10 am |
|
|
asmboy wrote: | Mr. T gave you good advice. \
you don't say which precise part you are using , but
If there is a sequential time dependent aspect to your program
you have no choice but to make it a part of main() .
or pick another part that offers the resolution you need
AND is faster than a slow poke delta-sigma design of this low end converter family. |
I use ccs mcp342x.C driver (In my case MCP3428-4ch,16 bit ADC) and modbus_example_slave.
The delay while wating adc is about half socond. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Fri Apr 03, 2015 9:08 am |
|
|
If the ADC needs you to wait, then you have several choices:
1) Rethink your code approach as already outlined.
2) Use a faster ADC.
3) Buffer the ADC. Add a tiny little PIC to just handle the ADC, and let this do the waiting.
1 is the easiest, you just need to change the way your code is modularized, and have the call to test available from the main, start the ADC, and then in your main do other jobs, occasionally calling the test. |
|
|
houssam313
Joined: 02 May 2015 Posts: 1
|
|
Posted: Sat May 02, 2015 4:01 pm |
|
|
Hi,
It is better to use state machine technique in the library :
Code: |
signed int32 read_adc_mcp(unsigned int8 address=MCP342X_ADDRESS)
{
switch (ADC_State)
{
///////////////////////////////////////////////////////////////////////////
case 0:
#if MCP342X_MODE == MCP342X_ONE_SHOT
i2c_start(MCP342X_STREAM); //send I2C start
i2c_write(MCP342X_STREAM, MCP342X_DEVICE_CODE | (address << 1)); //send write command
i2c_write(MCP342X_STREAM, MCP342X_START_CONVERSTION | MCP342X_MODE | MCP342X_BITS | MCP342X_GAIN); //initiate conversion
i2c_stop(MCP342X_STREAM); //send I2C stop
#endif
ADC_State = 1;
return ADC_SENTINEL_VALUE;
break;
///////////////////////////////////////////////////////////////////////////
case 1:
i2c_start(MCP342X_STREAM); //send I2C start
i2c_write(MCP342X_STREAM, MCP342X_DEVICE_CODE | (address << 1) | 1); //send read command
#if MCP342X_BITS == MCP342X_18BITS
result.b[2] = i2c_read(MCP342X_STREAM, 1); //read MSB 18 Bit mode
#endif
result.b[1] = i2c_read(MCP342X_STREAM, 1); //read 2nd MSB 18 Bit mode, read MSB 16, 14 or 12 Bit mode
result.b[0] = i2c_read(MCP342X_STREAM, 1); //read LSB
status = i2c_read(MCP342X_STREAM, 1); //read Status
if(bit_test(status,7)) //if RDY = 1, New conversion not ready
ADC_State = 2;
else
ADC_State = 3;
return ADC_SENTINEL_VALUE;
break;
///////////////////////////////////////////////////////////////////////////
case 2:
status = i2c_read(MCP342X_STREAM, 1); //read Status
if(bit_test(status, 7)) //until RDY = 0
return ADC_SENTINEL_VALUE;
status = i2c_read(MCP342X_STREAM, 0); //read Status, do nack
i2c_stop(); //send I2C stop
i2c_start(MCP342X_STREAM); //send I2C start
i2c_write(MCP342X_STREAM, MCP342X_DEVICE_CODE | (address << 1) | 1); //send read command
#if MCP342X_BITS == MCP342X_18BITS
result.b[2] = i2c_read(MCP342X_STREAM, 1); //read MSB 18 Bit mode
#endif
result.b[1] = i2c_read(MCP342X_STREAM, 1); //read 2nd MSB 18 Bit mode, read MSB 16, 14 or 12 Bit mode
result.b[0] = i2c_read(MCP342X_STREAM, 1); //read LSB
ADC_State = 3;
return ADC_SENTINEL_VALUE;
break;
///////////////////////////////////////////////////////////////////////////
case 3:
status = i2c_read(MCP342X_STREAM, 0); //read Status, do nack
i2c_stop(); //send I2C stop
#if MCP342X_BITS == MCP342X_18BITS
if(bit_test(result.b[2],1)) //if 18 Bit mode check sign bit
result.b[3] = 0xFF;
else
result.b[3] = 0;
#endif
ADC_State = 0;
#if MCP342X_BITS == MCP342X_18BITS
return(result.sint32);
#else
return(result.sint16);
#endif
break;
///////////////////////////////////////////////////////////////////////////
default:
break;
}
|
also define the ADC_SENTINAL_VALUE as
Code: |
#define ADC_SENTINEL_VALUE 0xFFFFFFFE
|
And to use it in main loop
Code: |
while(true)
{
ad1 = read_adc_mcp();
if(ad1 != ADC_SENTINEL_VALUE)
printf("val=%lu\r\n",ad1);
output_low(LED);
// delay_ms(DELAY);
output_high(LED);
// delay_ms(DELAY);
}
|
I Wish I help u |
|
|
|
|
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
|