LTC1286 SPI Read Problems

I'm trying to read from an LTC1286. This is a dumb SPI device that can only be read from, it cannot be written to.

My sample code is something like this:

  SPI.begin(); 
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE2);                // clock is idle high, and clock out on falling edge
  SPI.setClockDivider(SPI_CLOCK_DIV128);    // use 125kHz clock, LTC1286 can only do 12.5ksps maximum which is 150kHz @ 12 bits

  digitalWrite(channel, LOW);
  delayMicroseconds(16);
  int ah = SPI.transfer(0x00) & 0x0f;    // MSB, 4 bits only
  int al = SPI.transfer(0x00);
  digitalWrite(channel, HIGH);

  long val = (ah * 256) + al;  
  if (val == 0) val = 1;       // avoid NaN
  return val;

The data sheet (and timing diagram) for the LT1286 is here.. http://cds.linear.com/docs/en/datasheet/128698fs.pdf

My problem is that the readings I get fluctuate wildly. I would understand if the least-significant 1-3 bits are flipping randomly, but for the next-to-the-MSB bit to flip... seems a bit excessive.

Admittedly I have everything on a breadboard right now, so it could be analog noise. But I am not sure if I am talking to the LTC1286 properly. The data sheet says that after pulling CS low, the ADC will output one null bit, followed by data (MSB to LSB, 12 bits total).

Right now I am reading two bytes in a row. Since I am reading 16 bits,

  1. am I getting the null bit at the very left?
  2. right now I am masking the most significant nibble of the first byte. But this might be wrong...

I think your data needs more manipulating.
SPI will bring in a bit on every clock
Looks to me like you will see
x-x-x-B11-B10-B9-B8-B7
and then
B6-B5-B4-B3-B2-B1-B0-B1

so final (int) result might go together as
final = ( ((ah & B00011111)<<7) + (al >>1) );

Try some adjustments like that. I may be off 1 bit position with the rising edge/falling edge capturing.

I will try this...

In the meantime I manually bit-banged the CLK pin and managed to get data that made sense. Ugly, but works.

Good enough for a slow device.

I know the original thread is way old, but finding this thread helped me with my recent problem. I tried CrossRoads' suggestion and it worked. Here is my code:

/*
SS: pin 10
MOSI: pin 11
MISO: pin 12
SCK: pin 13
*/

#include <SPI.h>

const int ss_pin = 10;
uint8_t val1, val2;
uint16_t final;
float volts;

void setup() {
Serial.begin(9600);
pinMode (ss_pin, OUTPUT);
digitalWrite(ss_pin, HIGH);
SPI.begin();
}

void loop() {
SPI.beginTransaction(SPISettings(1000, MSBFIRST, SPI_MODE2));
digitalWrite(ss_pin, LOW);
val1 = SPI.transfer(0);
val2 = SPI.transfer(0);
digitalWrite(ss_pin, HIGH);
SPI.endTransaction();
final = ( ((val1 & B00011111)<<7) + (val2 >>1) );
volts = 5.0 * (float(final) / 2048.0);
Serial.print("val1 = ");
Serial.print(val1, BIN);
Serial.print(" val2 = ");
Serial.println(val2, BIN); 
Serial.print(" final = ");
Serial.print(final); 
Serial.print(" volts = ");
Serial.println(volts, 4); 

delay(1000);

}

I am not at all strong with C, so the above might have issues, but it does work.