user77514: I'm trying to use an Arduino Due to interface with an ADIS16364 IMU from Analog Devices (product info here) via SPI.
There are two modes for retrieving the measurements from this particular IMU (six 16 bit values, 3 acc, 3 gyros):

The first mode is, if I'm not wrong, the standard one with SPI, in which each successive transfer command retrieves the last data requested and indicates which one should be retrieved next.

The second possibility is a so called "burst mode". For this one you have to request the 0x3E00 register. After that, the IMU will burst out the six measurements (plus a few other bits of information like temperature and supply voltage). From the specs sheet:




The problem is, I can not manage to make the Arduino read the data using this burst mode. This is the code I'm using to test the communication:
#include <SPI.h>
#define SerialBT Serial2

short supply, xgyro, ygyro, zgyro, xacc, yacc, zacc, xtemp, ytemp, ztemp, aux;
volatile byte fDataIMUtoRead = 0;
int pauseBetweenTransfers;

void setup() {

  SerialBT.begin(230400);

  pinMode(52, OUTPUT);

  // Configure SPI
  SPI.begin(52);
  SPI.setClockDivider(52, 200); // 84e6/200 = 420kHz
  SPI.setDataMode(52, SPI_MODE3);
  SPI.setBitOrder(52, MSBFIRST);

  // Set sample rate
  float Fs = 1; // Target sampling frequency [Hz]
  float tb = 0.61035 * (Fs >= 12.7009) + 18.921 * (Fs < 12.7009);
  unsigned long tbsel = 0 * (Fs >= 12.7009) + 1 * (Fs < 12.7009);
  unsigned long Ns = (uint16_t) round((1000.0 - tb * Fs) / (tb * Fs));
  float Feff = 1000 / (tb * (Ns + 1));
  SerialBT.print("Selected freq: ");
  SerialBT.println(Feff, DEC);

  digitalWrite(52, LOW);  // Doesn't seem to be necessary
  SPI.transfer16(52, (0L << 15) | (0x36L << 8));                       delayMicroseconds(100);
  SPI.transfer16(52, (1L << 15) | (0x36L << 8) | (tbsel << 7) | Ns );  delayMicroseconds(100);
  SPI.transfer16(52, (0L << 15) | (0x36L << 8));                       delayMicroseconds(100);
  zgyro = SPI.transfer16(52, 0x00);
  digitalWrite(52, HIGH);  

  SerialBT.print("SMPL_PRD = ");
  SerialBT.println(zgyro, HEX);

  attachInterrupt(3, availableIMUData, RISING);
}

void loop() {

if (fDataIMUtoRead) {

SerialBT.print("Loop... ");

// Read values (standard mode)  
pauseBetweenTransfers = 100;
digitalWrite(52, LOW); // Doesn't seem to be necessary

        SPI.transfer16(52, 0x0400, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xgyro  = SPI.transfer16(52, 0x0600, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
ygyro  = SPI.transfer16(52, 0x0800, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
zgyro  = SPI.transfer16(52, 0x0A00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xacc   = SPI.transfer16(52, 0x0C00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
yacc   = SPI.transfer16(52, 0x0E00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);             
zacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);
  
digitalWrite(SS, HIGH);    

/*
// Read values (burst mode)
pauseBetweenTransfers = 5;
digitalWrite(52, LOW);    // Doesn't seem to be necessary 
  
         SPI.transfer16(52, 0x3E00);    delayMicroseconds(pauseBetweenTransfers);  // Request data burst
supply = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
xgyro  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
ygyro  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
zgyro  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
xacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
yacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
zacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
xtemp  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
ytemp  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
ztemp  = SPI.transfer16(52, 0x0000);
    
digitalWrite(52, HIGH);     
*/

SerialBT.println(zgyro, DEC); // Print the reading

fDataIMUtoRead = 0; // Reser the "there is new data"-flag

}    

}
void availableIMUData() {
fDataIMUtoRead = 1; // Set the "there is new data"-flag
}
The standard way to communicate seems to work without any problem, provided that I set the right delays after each transfer16 command. But I'm not able to make the Arduino read the data in burst mode (commented in the code above).
So does anybody have any ideas on how to make the Arduino retrieve the readings in this burst mode? I understand this is a tricky unless you have (had) access to the same hardware, but any suggestion will be welcome.
Thanks a lot.

user40646: First of all, this may not related to your question, but you are using old SPI methods setClockDivider(), setDataMode(), and setBitOrder() that has been deprecated since 2014. It is recommend to use use transactional SPI APIs which I have some explanation here.

Why I actually need those delays?

If you read page 6 of ADIS16364 datasheet, there is a tSTALL time between each data transmission that could be as long as 75uS (when operating on Low Power mode), this value can be much lower if you operate on Normal or Bust mode.

why this combination of delays with the 200 clock divider?

The clock divide set the clock used for the SPI SCLK rate, for Due a clock divide of 200 means 84,000,000 / 200 = 420,000Hz, Why this rate? again, you have to look into datasheet, on page 6 table 2, max fsck is 2MHz for Normal mode, and 1MHz for Bust mode, and only 300kHz at Low Power mode.

Shouldn't this be done automatically by the SPI library?

This is a wrong perception, SPI library do nothing than handling the communication. All the timing requirements are component/chip specific, and therefore if you want to communicate with the chip at SPI communication level, you will have to deal with all the timing requirements yourself. Most of the people in the Arduino community get used of using some pre-written library which was written by someone who care to read the datasheet and provide high level abstract API so that users don't need to deal with all the timing.

Any ideas on how to make the Arduino retrieve the readings in this burst mode?

Update
As suggested by the datasheet, "To start a burst read sequence, set DIN = 0x3E00", what this means is that you need to WRITE into the register 0x3E00 first to setup the burst mode. Fig 11. of the datasheet indicate that a WRITE operation would have a set most significant bit to 1, so you will need to send 0x3E00 | 0x8000 or 0xAE00 for writing into register 0x3E00. What you did is basically reading form 0x3E00, not writing into 0x3E00.
I re-read the datasheet and you are right, it should be okay to just send out 0x3E00. I never use an Arduino Due before, but I realised that the SPI.transfer16() might send out the 0x00 first instead of 0x3E. I modified the code to send out two bytes 0x3E and 0x00 separately using SPI.transfer()
I don't have the IMU, but I think the follow code should works for bust mode:
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));    //initialises SPI clock speed, mode and bit order
digitalWrite(SS, LOW);              // adjust this as per your chip select pin
SPI.transfer(0x3E);
SPI.transfer(0x00);
delayMicroseconds(1);               //bust mode only 1uS required as per datasheet
xgyro_out = SPI.transfer16(0x0000);
delayMicroseconds(1);
ygyro_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
zgyro_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
xaccl_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
yaccl_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
zaccl_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
digitalWrite(SS, HIGH);   // deselect slave
SPI.endTransaction();


77514: <p>I'm trying to use an Arduino Due to interface with an ADIS16364 IMU from Analog Devices (<a href="https://www.analog.com/en/products/adis16364.html#product-documentation" rel="nofollow noreferrer">product info here</a>) via SPI.</p>
<p>There are two modes for retrieving the measurements from this particular IMU (six 16 bit values, 3 acc, 3 gyros):</p>
<ol>
<li><p>The first mode is, if I'm not wrong, the standard one with SPI, in which each successive transfer command retrieves the last data requested and indicates which one should be retrieved next.</p>
</li>
<li><p>The second possibility is a so called &quot;burst mode&quot;. For this one you have to request the 0x3E00 register. After that, the IMU will burst out the six measurements (plus a few other bits of information like temperature and supply voltage). From the specs sheet:</p>
</li>
</ol>
<p><a href="https://i.stack.imgur.com/v5CBQ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/v5CBQ.png" alt="enter image description here" /></a>
<a href="https://i.stack.imgur.com/Fluov.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Fluov.png" alt="enter image description here" /></a></p>
<p>The problem is, I can not manage to make the Arduino read the data using this burst mode. This is the code I'm using to test the communication:</p>
<pre><code>#include &lt;SPI.h&gt;
#define SerialBT Serial2

short supply, xgyro, ygyro, zgyro, xacc, yacc, zacc, xtemp, ytemp, ztemp, aux;
volatile byte fDataIMUtoRead = 0;
int pauseBetweenTransfers;

void setup() {

  SerialBT.begin(230400);

  pinMode(52, OUTPUT);

  // Configure SPI
  SPI.begin(52);
  SPI.setClockDivider(52, 200); // 84e6/200 = 420kHz
  SPI.setDataMode(52, SPI_MODE3);
  SPI.setBitOrder(52, MSBFIRST);

  // Set sample rate
  float Fs = 1; // Target sampling frequency [Hz]
  float tb = 0.61035 * (Fs &gt;= 12.7009) + 18.921 * (Fs &lt; 12.7009);
  unsigned long tbsel = 0 * (Fs &gt;= 12.7009) + 1 * (Fs &lt; 12.7009);
  unsigned long Ns = (uint16_t) round((1000.0 - tb * Fs) / (tb * Fs));
  float Feff = 1000 / (tb * (Ns + 1));
  SerialBT.print(&quot;Selected freq: &quot;);
  SerialBT.println(Feff, DEC);

  digitalWrite(52, LOW);  // Doesn't seem to be necessary
  SPI.transfer16(52, (0L &lt;&lt; 15) | (0x36L &lt;&lt; 8));                       delayMicroseconds(100);
  SPI.transfer16(52, (1L &lt;&lt; 15) | (0x36L &lt;&lt; 8) | (tbsel &lt;&lt; 7) | Ns );  delayMicroseconds(100);
  SPI.transfer16(52, (0L &lt;&lt; 15) | (0x36L &lt;&lt; 8));                       delayMicroseconds(100);
  zgyro = SPI.transfer16(52, 0x00);
  digitalWrite(52, HIGH);  

  SerialBT.print(&quot;SMPL_PRD = &quot;);
  SerialBT.println(zgyro, HEX);

  attachInterrupt(3, availableIMUData, RISING);
}

void loop() {

if (fDataIMUtoRead) {

SerialBT.print(&quot;Loop... &quot;);

// Read values (standard mode)  
pauseBetweenTransfers = 100;
digitalWrite(52, LOW); // Doesn't seem to be necessary

        SPI.transfer16(52, 0x0400, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xgyro  = SPI.transfer16(52, 0x0600, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
ygyro  = SPI.transfer16(52, 0x0800, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
zgyro  = SPI.transfer16(52, 0x0A00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xacc   = SPI.transfer16(52, 0x0C00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
yacc   = SPI.transfer16(52, 0x0E00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);             
zacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);
  
digitalWrite(SS, HIGH);    

/*
// Read values (burst mode)
pauseBetweenTransfers = 5;
digitalWrite(52, LOW);    // Doesn't seem to be necessary 
  
         SPI.transfer16(52, 0x3E00);    delayMicroseconds(pauseBetweenTransfers);  // Request data burst
supply = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
xgyro  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
ygyro  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
zgyro  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
xacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
yacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
zacc   = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
xtemp  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
ytemp  = SPI.transfer16(52, 0x0000, SPI_CONTINUE);  delayMicroseconds(pauseBetweenTransfers);
ztemp  = SPI.transfer16(52, 0x0000);
    
digitalWrite(52, HIGH);     
*/

SerialBT.println(zgyro, DEC); // Print the reading

fDataIMUtoRead = 0; // Reser the &quot;there is new data&quot;-flag

}    
</code></pre>
<p>}</p>
<p>void availableIMUData() {<br />
fDataIMUtoRead = 1; // Set the &quot;there is new data&quot;-flag
}</p>
<p>The standard way to communicate seems to work without any problem, provided that I set the right delays after each transfer16 command. But I'm not able to make the Arduino read the data in burst mode (commented in the code above).</p>
<p>So does anybody have any ideas on how to make the Arduino retrieve the readings in this burst mode? I understand this is a tricky unless you have (had) access to the same hardware, but any suggestion will be welcome.</p>
<p>Thanks a lot.</p>
 40646: <p>First of all, this may not related to your question, but you are using old SPI methods <code>setClockDivider()</code>, <code>setDataMode()</code>, and <code>setBitOrder()</code> that has been deprecated since 2014. It is recommend to use use transactional SPI APIs which I have some explanation <a href="https://arduino.stackexchange.com/a/79760/40646">here</a>.</p>
<blockquote>
<p>Why I actually need those delays?</p>
</blockquote>
<p>If you read page 6 of <a href="https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16364.pdf" rel="nofollow noreferrer">ADIS16364 datasheet</a>, there is a tSTALL time between each data transmission that could be as long as 75uS (when operating on Low Power mode), this value can be much lower if you operate on Normal or Bust mode.</p>
<blockquote>
<p>why this combination of delays with the 200 clock divider?</p>
</blockquote>
<p>The clock divide set the clock used for the SPI SCLK rate, for Due a clock divide of 200 means 84,000,000 / 200 = 420,000Hz, Why this rate? again, you have to look into datasheet, on page 6 table 2, max fsck is 2MHz for Normal mode, and 1MHz for Bust mode, and only 300kHz at Low Power mode.</p>
<blockquote>
<p>Shouldn't this be done automatically by the SPI library?</p>
</blockquote>
<p>This is a wrong perception, SPI library do nothing than handling the communication. All the timing requirements are component/chip specific, and therefore if you want to communicate with the chip at SPI communication level, you will have to deal with all the timing requirements yourself. Most of the people in the Arduino community get used of using some pre-written library which was written by someone who care to read the datasheet and provide high level abstract API so that users don't need to deal with all the timing.</p>
<blockquote>
<p>Any ideas on how to make the Arduino retrieve the readings in this burst mode?</p>
</blockquote>
<p><strong>Update</strong></p>
<p><s>As suggested by the datasheet, &quot;To start a burst read sequence, <strong>set DIN = 0x3E00</strong>&quot;, what this means is that you need to <strong>WRITE</strong> into the register 0x3E00 first to setup the burst mode. Fig 11. of the datasheet indicate that a WRITE operation would have a set most significant bit to 1, so you will need to send <code>0x3E00 | 0x8000</code> or <code>0xAE00</code> for writing into register <code>0x3E00</code>. What you did is basically reading form <code>0x3E00</code>, not writing into <code>0x3E00</code>.</s></p>
<p><strong>I re-read the datasheet and you are right, it should be okay to just send out <code>0x3E00</code>. I never use an Arduino Due before, but I realised that the SPI.transfer16() might send out the <code>0x00</code> first instead of <code>0x3E</code>. I modified the code to send out two bytes <code>0x3E</code> and <code>0x00</code> separately using <code>SPI.transfer()</code></strong></p>
<p>I don't have the IMU, but I think the follow code should works for bust mode:</p>
<pre><code>SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));    //initialises SPI clock speed, mode and bit order
digitalWrite(SS, LOW);              // adjust this as per your chip select pin
SPI.transfer(0x3E);
SPI.transfer(0x00);
delayMicroseconds(1);               //bust mode only 1uS required as per datasheet
xgyro_out = SPI.transfer16(0x0000);
delayMicroseconds(1);
ygyro_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
zgyro_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
xaccl_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
yaccl_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
zaccl_out = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
data16    = SPI.transfer16(0x0000);  
delayMicroseconds(1);
digitalWrite(SS, HIGH);   // deselect slave
SPI.endTransaction();
</code></pre>
