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

ADS8344

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



Joined: 21 Sep 2006
Posts: 6

View user's profile Send private message

ADS8344
PostPosted: Mon Jan 08, 2007 7:31 am     Reply with quote

Hi,

I've got the PIC18F452 prototyping board, and I am trying to use a TI ADS8344 analog to digital converter.

My problem is that after sending the control byte to the ADS, I get the data back spread over three bytes instead of two. So at this point I am shifting the data and concatenating the bytes together.

Attached is my code. I have tried an open loop delay between the read and write functions, I have tried waiting for the BUSY signal (ADS pin 16) to go low before reading, and I have experimented with using the in_data = spi_read(out_data) method instead of separate spi_write() and spi_read() commands.

please help!
thanks

Code:

#include <18F452.h>
#device ICD=TRUE ADC=16
#fuses HS,NOWDT,NOPROTECT,NOLVP, NOBROWNOUT
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7)

//Define Configuration Schematic
#define CS      PIN_E0
//#define CLK      PIN_C3
//#define DI      PIN_C5
//#define DO      PIN_C4
//#define BUSY      PIN_E1


//Main Program
void main()
{
   //declarations
   int8   adc_chan0 = 0b10000100;
   int8   adc_in1, adc_in2, adc_in3;
   int16  an;

   //setup the spi line
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
   output_high(CS);

   //setup PIC adc
   setup_adc_ports(ALL_ANALOG);                  //set up adc ports
   setup_adc(ADC_CLOCK_INTERNAL);                  //set to internal clock
   set_adc_channel(1);                           //set adc channel

   while(1)
   {
      //communicate with ads8344
      output_low(CS);
      spi_write(0b10000111);
      adc_in1 = spi_read(0x00);
      adc_in2 = spi_read(0x00);
      adc_in3 = spi_read(0x00);
      output_high(CS);

      //read built-in adc
      an = read_adc();

      //print to screen
      printf("\r\n%u\t%u\t%u\t%lu",adc_in1,adc_in2,adc_in3,an);
   }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jan 08, 2007 12:35 pm     Reply with quote

The most important thing about SPI is to setup the correct mode.
Look at any of the SPI timing diagrams in the ADS8344 data sheet.
http://focus.ti.com/lit/ds/symlink/ads8344.pdf
You can see that the data is sampled on the rising edge of DCLK.
(The rising edge is in the middle of the data cell). Also, the idle state
of DCLK is a low level.

Now look at this chart of SPI modes:
http://www.totalphase.com/support/articles/article03/#modes
Notice that Mode 0 fits the timing relationship described above.

Now you know the SPI mode. The next question is, how to setup
the mode in CCS ? Look at this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=29059&start=36
ckielstra has posted a convenient way of defining the SPI modes:
Code:

#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

From this, you can immediately see that your code is using the
wrong mode. You're using Mode 1. Looking back at the chart
that describes the modes, you can see that Mode 1 is completely
wrong for the ADS8344. It samples on the wrong edge.

To fix the mode, put the #defines for the mode statements above main().
Then change the setup_spi() function to use the constant for Mode 0:
Code:

setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16);

There might be other problems in your code, but at least this will
get you using the correct SPI mode.
jgrauer



Joined: 21 Sep 2006
Posts: 6

View user's profile Send private message

PostPosted: Mon Jan 08, 2007 2:08 pm     Reply with quote

Thanks for your reply.

So before I had two blank bits before the data started streaming, meaning I had to read the SPI bus a third time to get the 16 bits of data. After correcting the SPI mode, I have only one blank bit before the data streams, so that I still have to make three reads to capture the full 16 bit data stream. Reading the section 'External Clock Mode' in the ADS8344 manual, I guess this is to be expected. In the penultimate paragraph in that section they give another method which I don't completely understand how to implement; they say to read the LSB at the same time the new control bit is being written, which should result in 24 clock cycles per conversion. I figured this means I should use the following lines in my code:

Code:
      output_low(CS);                           //select the ADS8344
      spi_write(chan0);                        //send control byte
      ads_in1 = spi_read(0x00);                  //read
      ads_in2 = spi_read(0x00);
      ads_in3 = spi_read(0x00);
      output_high(CS);                        //release the ADS8344


When I do this, I get the same result as I described above, except I am reading the least significant byte before the other two. Does anyone have a suggestion? Is it possible to read these 16 bits with two reads, or am I doomed to using three bytes to concatenate and shift?

Attached is my code, which is slightly modified from what I posted before.

thanks!

Code:
// ADS8344_1channel.c
//
// This program compares one channel of the ads8344 and the
// PIC's internal adc
//

//PIC CONFIGURATION
#include <18F452.h>
#device ICD=TRUE ADC=16
#fuses HS,NOWDT,NOPROTECT,NOLVP, NOBROWNOUT
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7)



//CONFIGURATION SCHEMATIC
#define CS      PIN_E0
#define CLK      PIN_C3
#define DI      PIN_C5
#define DO      PIN_C4
#define BUSY   PIN_E1

#define chan0 0b10000111
#define chan1 0b10010111
#define chan2 0b10100111
#define chan3 0b10110111
#define chan4 0b11000111
#define chan5 0b11010111
#define chan6 0b11100111
#define chan7 0b11110111

#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)



//FUNCTION PROTOTYPES
int16 ads8344_data(int8, int8, int8);



//MAIN PROGRAM
void main()
{
   //declarations
   int8   ads_in1, ads_in2, ads_in3;
   int16  an, ads_16;

   //setup the spi line
   setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16);
   output_high(CS);

   //setup PIC adc
   setup_adc_ports(ALL_ANALOG);                  //set up adc ports
   setup_adc(ADC_CLOCK_INTERNAL);                  //set to internal clock
   set_adc_channel(1);                           //set adc channel

   while(1)
   {
      //communicate with ads8344
      output_low(CS);                           //select the ADS8344
      spi_write(chan0);                        //send control byte
      ads_in1 = spi_read(0x00);                  //read
      ads_in2 = spi_read(0x00);
      ads_in3 = spi_read(0x00);
      output_high(CS);                        //release the ADS8344

      ads_16 = ads8344_data(ads_in1,ads_in2,ads_in3);   //reduce the data

      //read built-in adc
      an = read_adc();

      //print to screen
      printf("\r\n%lu\t%lu",ads_16,an);
      //printf("\r\n%u \t %u \t %u \t %lu",ads_in1,ads_in2,ads_in3,an);
   }
}



//ADS8344 DATA REDUCTION
int16 ads8344_data(int8 byte2, int8 byte1, int8 byte0)
{
   //Declarations
   int16 output;
   int32 temp;

   temp = make32(byte2,byte1,byte0,0x00);            //concatenate bytes
   shift_left(&temp, 32, 0);                     //shift 1 byte to the left
   output = make16( make8(temp,3), make8(temp,2) );   //mask out the data bits
   return(output);
}
Ttelmah
Guest







PostPosted: Mon Jan 08, 2007 4:36 pm     Reply with quote

Top of page 14 of the data sheet.
The problem is that the 'busy' signal, does not drop till one clock is received. Hence 25 clocks are actually needed to transfer the three bytes. Eight for the control word, one for the busy transition, 16 for the data bytes. You can then optionally clock another 7 which just clock out zeros.
Don't fiddle around catenting the data. Get it like this:
Code:

union {
   int16 words[2];
   int8 bytes[4];
} joiner

   output_low(CS);                           //select the ADS8344
   spi_write(chan0);                         //send control byte
   joiner.bytes[3] = spi_read(0x00);  //read
   joiner.bytes[2] = spi_read(0x00);
   joiner.bytes[1] = spi_read(0x00);
   output_high(CS);                         //release the ADS8344
   //Note that using the array costs nothing here in speed, since
   //the values are directly addressed.
   shift_left(&joiner.bytes[1],3,0);

   printf("\r\n%lu",joiner.word[1]);

The trick here is that by reading the three returns inot three successive bytes, a single bit rotation, moves these to rebuild the required 16bit value. The union allows this to be accessed.
I think I have got the indexes, and things right, but 'no guarantees'...

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