SPI Communication with A/D Converter AD7687 - SPI.trasfer() not applicable

Hi Everyone,

I'm working on a project where I will be using an Arduino to interface to a relatively high speed A/D converter using the SPI bus. The A/D converter I plan to use is an Analog Devices AD7687, 16 bit 250 ksps A/D converter ( Datasheet: http://www.analog.com/static/imported-files/data_sheets/AD7687.pdf). The reason for my post is that after going over the datasheet for the AD7687 and the Arduino documentation many times it seems that the Arduino SPI library is not really set up to communicate with a part like this. However, I wanted to get a second opinion to make sure that I am not missing anything.

It seems that the Arduino SPI library is only set up for a Command>Response type of communication; where the Arduino would send a byte over the SPI bus and then receive a response from a slave device. The problem that I am running into is that the AD7687 does not communicate like this. Essentially how the device works is that a LOW to HIGH transition on the CNV pin tells the device to start a new conversion, where it digitizes the analog value on its input pin. After the digitization is complete the CNV pin can be set low at which pot the master (Arduino) can clock out the 16 bits of data from the device. Starting on page 18 of the datasheet it outlines the communication protocol in more detail.

Based on what I have read about the Arduino SPI library it does not look like it will work for reading from this sort of SPI device. I'm guessing the best route right now is writing my own library to implement this protocol, unless anyone in the community has any suggestions on what I should do.

Since speed is a major concern of mine I think the best route would be implementing the protocol via direct port manipulation rather than digitalWrite() since that seems to be very slow.

Thanks for any help,

Charlie

Pages 17+ talk about the conversion types.
Looks to me like you need to control the Conversion pin similar to controlling the Chip select pin.
I would use direct port manipulation for both if speed is a concern. I don't normally use digitalWrite when using SPI.transfer().

Looks to me like you need to control the Conversion pin similar to controlling the Chip select pin.

I would use direct port manipulation for both if speed is a concern.

Yes that was my intention

I don't have the board with the A/D converter on it fully designed yet so I don't have a way to test anything yet; just trying to plan ahead. What I'm confused about, I guess, is how SPI.transfer() works. Lets say I manipulate the CNV pin with direct port manipulation and tell the A/D converter to read a sample, can I call SPI.transfer() with no argument to then read the data from the chip? It looks like SPI.transfer() is designed to first have to send a "command" before it can read data back. Since I don't need to send a "command" in order to read data (i just need to manipulate the CNV pin) what I really need is a function, for example: SPI.read(), that would read data from the SIP bus without first needing to send some sort of command to the slave device, but I'm not sure something like that exists.

Any suggestions?

Thanks for your help,

Charlie

digitalWrite (CNV, LOW);
digitalWrite (CNV, HIGH);
digitalWrite(csPin, LOW);
byteOne = SPI.transfer(0); // read data in on MISO pin while sending out 0 on MOSI.
byteTwo = SPI.transfer(0); // read data in on MISO pin while sending out 0 on MOSI.
digitalWrite (csPin, HIGH);

Wow thanks!

If that works It really is so simple! :slight_smile: I see one potential problem though. When SPI.transfer(0) runs. The SPI clock will clock out the 8 bits on the MOSI pin (send the value of zero), however, on the AD7687 once the CNV pin has been manipulated and it has digitized the sample it will begin sending data on the bus as soon at the SPI clock begins. The problem is, that with this code, when the SPI clock begins the Master is still sending the zero value and not yet looking for any incoming data. So it will miss the first half of the incoming data. Or is that not how the SPI bus works?

The problem is, that with this code, when the SPI clock begins the Master is still sending the zero value and not yet looking for any incoming data. So it will miss the first half of the incoming data. Or is that not how the SPI bus works?

That is not how it works. The SPI is looking for incoming data immediately. When you are writing the first byte out, the SPI is reading the first byte in at the same time.

That is not how it works. The SPI is looking for incoming data immediately. When you are writing the first byte out, the SPI is reading the first byte in at the same time.

Oh, okay. Thanks for the info. This is my first time attempting to communicate via SPI with the Arduino, so my knowledge of the interface is not that good. This certainly helps a lot. Thanks everyone for your time.

Charlie

Nick Gammon did a nice write up on it here, with data captures shown

Nick Gammon did a nice write up on it here, with data captures shown
Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino

Thanks for that link it was very helpful and thorough. I think I'm understanding SPI on the Arduino a little bit better now. I'll be sure to keep everyone as this project progresses.

Charlie

I know this conversation is old, but this you manage to get it working? I am using the same ADC.

Are these commands enough to read the data input:

digitalWrite (CNV, LOW);
digitalWrite (CNV, HIGH);
digitalWrite(csPin, LOW);
byteOne = SPI.transfer(0); // read data in on MISO pin while sending out 0 on MOSI.
byteTwo = SPI.transfer(0); // read data in on MISO pin while sending out 0 on MOSI.
digitalWrite (csPin, HIGH);

ty