Receiving more than one byte as response from SPI

I'm going to make a Maxim MAX11040K talk with a Arduino Due. The MAX11040K Is a 4 channel, 24bit ADC... as such, when I want to read the data register, the response will be 96bits long... in fact, the response will be a variable amount of bytes depending on which register I read from it, which may be a small problem - but not too large I think.

The problem is, for each command, the Due Extended SPI tutorial page seems to expect that I will receive only one byte as a response instead of 12 bytes. Reading the MAX11040K data sheet, I just send the 8bit command once, and then I will get back anywhere from 1 to 12 bytes back. Since using SPI_CONTINUE with SPI.transfer() implies that the command is sent one more time, I don't think that's a solution. Any ideas?

EDIT: This is what I have so far:

#include <SPI.h>
#include "customtypes.h"
#define ADC_CS 22
#define DAC_CS 23
#define ADC_READ 1
#define ADC_WRITE 0
#define ADC_SAMPLING-INSTANT-CONTROL-REG 0x40 //32bit
#define ADC_DATARATE-CONTROL-REG 0x50 //16bit
#define ADC_CONFIGURE-REG 0x60 //8bit
#define ADC_DATA-REG 0x70 //24*4bit


//the following pin numbers may change at any time


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  SPI.begin(ADC_CS);
  SPI.begin(DAC_CS);
  SPI.setClockDivider(2); //runs it at 42MHz
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0, DAC_CS); // page 29
  SPI.setDataMode(SPI_MODE2, ADC_CS); // page 16
}
void loop() {
  // put your main code here, to run repeatedly: 

}
void dac_talk(int cmd, int number){
  if(number > 131071 || number < -131072){
    Serial.println("Value outside 17bit range!");
  }
  dacSPIframe command;
  command.bitfield.value = number;
  command.bitfield.cmd = cmd;
  SPI.transfer(DAC_CS,command.bytes[2],SPI_CONTINUE);
  SPI.transfer(DAC_CS,command.bytes[1],SPI_CONTINUE);
  SPI.transfer(DAC_CS,command.bytes[0]);
};

void adc_read(byte address, byte resultcontainer[]){
  byte command;
  // if you want to read, add 128
  command = command+0x80;
  Serial.print("Sending this command to ADC: ");
  Serial.print(command,BIN);
  Serial.print("\n");
  SPI.transfer(ADC_CS,command);
};

Normally each SPI.transfer returns one byte, so you call it 12 times, right? However I'm not an expert on the Due.

Moving this to the Due section.

But calling SPI.transfer() 12 times means sending a command 12 times.... I only need to send it once!

Hi,

send your 8 bit command

Spi.transfer(CS_pin, command, SPI_CONTINUE);

and then for every byte (n) you want to read an other

byte_1 = SPI.transfer(CS_pin, 0x00, SPI_CONTINUE);
byte_2 = SPI.transfer(CS_pin, 0x00, SPI_CONTINUE);
...
byte_n = SPI.transfer(CS_pin, 0x00);

not tested, but with SPI diagram on page 17, it should work :slight_smile:
http://datasheets.maximintegrated.com/en/ds/MAX11040K-MAX11060.pdf

if you want to write more than one byte it works the same

I use it this way for 8/16/32 bit read & writes to AD5666 / MCP4261 and it works fine (if only one CS is used in the sketch).
[edit]Multiple usage of the predefined CS work now!
see [solved] due extended SPI problem - Arduino Due - Arduino Forum

background:
with SPI_Continue the CS_pin keeps low
and every other transfer 8 bits of MISO are clocked in
so for your SPI slave it looks like one big command comming in
the last SPI.transfer without SPI_CONTINUE let the CS_pin go to high again.

randomshinichi:
But calling SPI.transfer() 12 times means sending a command 12 times.... I only need to send it once!

Read my link. SPI is always two-way transfer. Usually the receiving end will accept a NOP or similar.

See this from the datasheet:

You can see that after the command DIN is low (in other words you are sending 0x00 bytes).

From the data sheet, the minimum period for SCLK is 50ns which is 20 MHz frequency ... this means that the clock divisor would have to be at least 5 for 16.8 MHz. I would suggest using the default (4 MHz) until communication is established.

From my experience with SPI:

This would require using the DUE's port as an SPI Master. The master controls the SCLK, so in order to receive any information, you need to send information. The SCLK will toggle only 8 times for each byte sent out on the MOSI line. At the same time, 8 BITS of information will be received on the MISO line. You'll need to use SPI_CONTINUE with the transfer function in order to hold the CS line low. After each byte, you'll need to read the bits received, then continue this process until completed ... the last transfer call will not use SPI_CONTINUE so the CS line can go HIGH.

When in SPI master mode, there is no way to get clock pulses on SCLK unless data is sent on MOSI. Even if its not a command or useful information - in this case just consider it dummy data where its only purpose is to get another 8 SCLK pulses for each byte sent.

Got it, thanks very much for your answers!