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 CCS Technical Support

problem in interfacing LTC2410 with 18LF2520
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

problem in interfacing LTC2410 with 18LF2520
PostPosted: Mon Jul 06, 2015 2:08 am     Reply with quote

Hardware Connections:
18LF2520 --------- LTC2410
PIN C4 ---------- SDO
PIN C3 --------- SCK
PIN C1 --------- CS

Below is the test code:
Code:

#include "18F2520.h"
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP      // Internal oscillator
#use delay(clock=1000000)      // 1Mhz

#define A2D_CSI       PIN_C1     
#define A2D_SCLK      PIN_C3     
#define A2D_SDO      PIN_C4   

int32 Read_A2D(void)
{
   int32 A2D_COUNTS;
   int i;

   output_high(A2D_SCLK);
   delay_us(100);
   output_high(A2D_CSI);
   output_low(A2D_SCLK);
   output_low(A2D_CSI);

   while((input(A2D_SDO))==1); //wait for /EOC to go low...

   for(i=4;i>0;i--) //I don't need to use these first 4 bits
   {
      output_high(A2D_SCLK);
      delay_us(5);
      output_low(A2D_SCLK);
      delay_us(5);
   }

   for(i=20;i>0;i--)      //Set i = number of bits to read
   {                     
      output_high(A2D_SCLK);
      delay_us(5);
      shift_left(&A2D_COUNTS,4,input(A2D_SDO));
      output_low(A2D_SCLK);
      delay_us(5);
   }
   output_high(A2D_CSI);

   return A2D_COUNTS;
}

void main()
{
   int32 A2D_value;
   setup_adc_ports(NO_ANALOGS|VSS_VDD);         // No analogs
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   
   setup_comparator (NC_NC_NC_NC);      // Disable comparator

   while(1)
   {
          A2D_value = Read_A2D();
          delay_ms(200);
          // display the adc value on lcd
    }
}


When i run this code, I get the output of 709931 in the display. When the change the input voltage at LTC2410, the display value is not changing.

Please help
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 2:54 am     Reply with quote

Look again at the data sheet.

You are operating the CS line. This means it'll be running in _internal_ SCK mode, which means _it_ generates the SCK, and you have to sample when it says....

I think you want to be in the external serial clock mode, Figure 7.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 4:05 am     Reply with quote

Very Sorry. There is a mistake on the hardware.
SCK and SDO are wrongly connected. Now solved the problem.

I require a solution for a problem.
Voltage at IN+: 0.7V
Voltage at IN-: 0.7V

When I increase the voltage at IN+, the LTC2410 produces the output code which increases from 0. I see it on LCD.

When I decrease the voltage at IN-, it produces some 6 digit value on the display.

What are those values? how to calculate it.
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 5:31 am     Reply with quote

It could be 'garbage' caused by the LCD display driver if you're not decoding the 32 bit data correctly from the ADC.
It also could be 'noise' or EMI....
You should post examples of input voltages VS results as well as the 'math' and LCD driver for more help.

Unless you're really,really good at analog PCB design getting that ADC to run 'right' will be a huge challenge!

Jay
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 7:54 am     Reply with quote

Hi,

For clarity and simplicity, I'd rewrite your 'ReadA2D' routine to extract all 24 bits of data from the LTC2410 in one pass. Once you have all the data, it's a simple matter to shift the data to remove the unwanted/unneeded bits.

John
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 8:05 am     Reply with quote

Had a quick read of the ADC datasheet and you do need to read in all 32 bits, after that then parse to get the 24 bits of the adc result.

Also be sure to have a solid 1ms delay before reading the ADC for the first time. It needs '0.5 ms' after power up to properly initialize itself.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 9:10 am     Reply with quote

Particularly so, because you need the sign bit....
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 11:29 pm     Reply with quote

Thanks. Let me read all 32 bits and parse it to get 24 bits.

Meanwhile i tried to measure the pulses at SCO and SCK lines. There are no pulses seen on the scope.

This looks to be strange.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 11:59 pm     Reply with quote

modified code to capture the 32 bit data.

Code:
int32 Read_A2D(void)
{
   int32 A2D_COUNTS;
   int i;

   output_high(A2D_SCLK);
   delay_us(100);
   output_high(A2D_CSI);
   output_low(A2D_SCLK);
   output_low(A2D_CSI);

   while((input(A2D_SDO))==1); //wait for /EOC to go low...

   for(i=32;i>0;i--)      //Set i = number of bits to read
   {                     
      output_high(A2D_SCLK);
      delay_us(5);
      shift_left(&A2D_COUNTS,0,input(A2D_SDO));
      output_low(A2D_SCLK);
      delay_us(5);
   }
   output_high(A2D_CSI);

   return A2D_COUNTS;
}


Is this routine is correct to capture the 32 bit data?
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 8:08 am     Reply with quote

Hi hemnath,

Here is a routine I've used for years with the TC77 temperature sensor. You could easily modify it to suit your needs:

Code:

   for (iIndex=16; iIndex!=0; iIndex--)
   {
      output_high(TC77_SCK); //clock hi 
      if (input(TC77_Data))
         bit_set(Data,iIndex - 1);
      output_low(TC77_SCK); //clock lo
      delay_us(10);
   }


john
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 11:17 am     Reply with quote

Lets start with a simple comment. _Use the tools_....

The chip uses a sub version of SPI. The compiler can do this for you.

So:
Code:

#include "18F2520.h"
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP      // Internal oscillator
#use delay(clock=1000000)      // 1Mhz

#define A2D_CSI       PIN_C1     
#define A2D_SCLK      PIN_C3     
#define A2D_SDO      PIN_C4   

#use spi(MASTER, DI=A2D_SDO, CLK=A2D_SCLK, BAUD=100000, BITS=32, MODE=1, stream=LTC)

signed int32 Read_A2D(void)
{
   union
   {
      signed int32 rval;
      unsigned int32 raw;
   } temp=0;
   temp.raw=spi_xfer(LTC,0,32);
   //Now need to sign extend the value
   if (bit_test(temp.raw,29))
   {
      //-ve value
      temp.raw |=0xE000; //turn on top 3 bits
   }
   else
   {
      temp.raw &=0x01FFF; //only use low 28bits
   }
   return temp.rval;
}
   

void main()
{
   signed int32 A2D_value;
   setup_adc_ports(NO_ANALOGS|VSS_VDD);         // No analogs
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   output_low(A2D_CSI);
   
   setup_comparator (NC_NC_NC_NC);      // Disable comparator
   //Now need to trigger a dummy read to start the conversion
   A2D_value=Read_A2D();
   while(1)
   {
          delay_ms(200); //delay before reading the first time
          A2D_value = Read_A2D();
          // display the adc value on lcd
          //remember this is a _signed_ value
   }
}


Now, no guarantees, but mode 1, should hold the clock low between the words, and sample on the rising edge (correct for this chip).
The sample will begin each time the transfer finishes (hence trigger a dummy sample before starting the loop), so there will always need to be enough time for the sample to complete between each reading (or you can read the EOC bit).
The data is a 29bit signed value. If the top bit is set (so -ve), then all the bits above this need to be set to give a signed int32.
Realise that you will get values like 'FFF7' if you look at the value in hex - this is -8. Display as a signed value to get the 'useable' value.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 10:32 pm     Reply with quote

@Ttelmah: I tried to display the values. But the values keeps on changing as,
7141, 2339, 8125, 7929, 6839, ....

@ezflyr: Thank you. I will try your code.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 10:42 pm     Reply with quote

@ezflyr: Tried your code. To convert 32 bit to 24 bit, i used the below routine inside the while loop
Code:
        delay_ms(200); //delay before reading the first time
      A2D_value = Read_A2D();

         bit_clear(A2D_value, 31);bit_clear(A2D_value, 30);bit_clear(A2D_value, 29);
         A2D_value = A2D_value >> 5;
            // to display the value
 


It displays 6884860 on LCD. Sad
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Thu Jul 09, 2015 1:15 am     Reply with quote

That does not convert the value.

You need to understand how signed values work.
The commonest form is called 2's complement.
Here 0000000 = 0
00000001 = 1
11111111 = -1

Now if you have (say) a 4 bit 2's complement value, stored in an 8bit integer, the conversion becomes:
Code:

    if (bit_test(val,3))
    {
        //here a -ve number - we need to set _all_ the bits between
        //the 'sign' bit in this number, and the top of the byte
        val |= 0b11110000; //turn on top four bits
    }
    else
    {
        //here a +ve number. We need to ensure all the upper bits
        //are 0
        val &= 0b00001111; //turn off the top four bits
    }


Now if you start with 'val' equal to 1, it gets left as 1.
However if it is 0b1111 (-1 in a 4bit value), it gets converted to
0b11111111 which is -1 in a 8bit value.

Then printf, using %3d, would print -1, as required.

This is called 'sign extending'. The sign bit has to be 'extended' to the top of the number.

Unless you do sign extending, you will get insane values if you are close to zero, and values go -ve. This is what your code is showing.

Now, a comment here, my code outputs the whole 29bits. You need to divide the _signed_ value by 32.

Code:

   A2D_value = Read_A2D();
   A2D_value/=32;


You must use division (not rotation), or you are back to the same problem with the sign.....

Now seriously, depending on how noisy the environment is the values from my code, are then quite reasonable:

223, 73, 253, 247, 213

Depending on your Vref, this would correspond to a few _uV_.....

It's worth then also understanding that you are dealing with a device sensitive to the tiniest signal. _Fractions_ of a uV/count. This is not something that can be tested on a conventional breadboard (except possibly by placing it inside a Faraday cage). If you have this on a simple board on the bench, expect to see hundreds of counts if you just move your hands near it. You need a really good grounded test station, with the board laid out with well designed analog paths kept separate from the digital circuitry, and a super stable Vref.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Thu Jul 09, 2015 4:46 am     Reply with quote

Thanks Ttelmah for your valuable comments.

I have designed a PCB and components are soldered and testing on it. (Not testing on breadboard).

Measured Vref: 3.2938V

Measured Input signal, Vin = IN+ - IN- => 0.00048V.

I wrote a simple routine to capture all 32 bits data and parsing it to convert to 24 bit.

But the problem is, even when my reference voltage and input signal is stable, the value on the display keeps on rolling for steady input signal. Well There could be any other problem with the below routine.

Code:
int32 Read_A2D(void)
{
   int i;
   signed int32 data = 0;

   output_high(A2D_SCLK);
   delay_us(100);
   output_high(A2D_CSI);
   output_low(A2D_SCLK);
   output_low(A2D_CSI);

   data = 0;

   for (i = 32; i!=0; i--)
   {
      output_high(A2D_SCLK); //clock hi
      delay_us(5);
      if (input(A2D_SDO))
      bit_set(Data, i - 1);
      output_low(A2D_SCLK); //clock low
      delay_us(5);
   }

   output_high(A2D_CSI);

   return data;
}


Values rolls like: 3125, 1518, 1497, 702, 1078, 2352, 1976, ... My input signal will change worst case of 4uV.

For 1uV = 5 bits will get increase. For these change in 4uV, max of 20 bits should get increased, right? but it is changing in the order of 1000.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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