AD7606 Library for mbed

Dependents:   AD7606_demo

This is my first attempt to develop a library to control an Analog Devices' AD7606BSTZ (8-channels, 16-bits, 200 kHz simultaneous sampling ADC) connected to an mbed enabled processor via an SPI port; I need to use this ADC in an applications requiring many simultaneous sampling analog input channels.

Until now the library has been tested with a FRDM-KL25Z and FRDM-K64F using this breakout board from ARMFLY, a Shenzhen-based Chinese Company, that I found on Aliexpress:

/media/uploads/frada/ad7606_breakout.jpg

It works well, at least for my needs.

Some important notes:

1) The AD7606 on the breakout board comes enabled to work in parallel mode, that is to tranfer the conversion results on a 8- or 16-bits wide data bus; to enable the SPI mode, it is mandatory to remove resistor R2 (10 kohm) and to solder it in place of R1.

2) as per the suggestions on the AD7606 data-sheet, when using the SPI connection, DB7 assumes the role of DOUTA and DB8 assumes the role of DOUTB; all remaining lines of parallel data bus should be connected to ground;

3) my library uses only DOUTA (DB7) to shift-out the conversion results of all channels; this is documented in the AD7606 data sheet:

SERIAL INTERFACE (PAR/SER/BYTE SEL = 1)

... Data can also be clocked out using just one DOUT line, in which case it is recommended that DOUTA be used to access all conversion data because the channel data is output in ascending order. For the AD7606 to access all eight conversion results on one DOUT line, a total of 128 SCLK cycles is required. ...

4) the 8 T/H (track and hold) devices in the AD7606BSTZ are divided in 2 groups of 4; each group being controlled by a CONVST line. I connected the two lines together to trigger the hold phase at the same time for all 8 T/H.

5) Until now I'm unable to find the cause of a problem with reading the correct status of the BUSY pin of the AD7606 (the while(_busy) loop in readAnalog and readRaw methods seems to hang, nonetheless the BUSY pin goes low after the conversion completion), so I am forced to wait for a fixed time (5 us) after the CONVST pulse to read the conversion result. However the conversion time is a function of the oversampling factor programmed using pins OS0, OS1, OS2 of the AD7606.

ad7606.cpp

Committer:
frada
Date:
2015-01-20
Revision:
4:9341319c0d8e
Parent:
3:ca87f4989281

File content as of revision 4:9341319c0d8e:

/***************************************************************************
 * @author Francesco Adamo
 *
 * @section LICENSE
 *
 * Copyright (c) 2015 Francesco Adamo, Italy
 *
 * @section DESCRIPTION
 *
 *  AD7606.CPP
 *  Source file for AD7606 class library
 *  The AD7606BSTZ is a 16-bits, 8-channels, SPI/Parallel-interfaced ADC from Analog Devices
 *  
*****************************************************************************/

#include "ad7606.h"


// Constructor
AD7606::AD7606(PinName MISO, PinName SCLK, PinName CS, PinName CONVST, PinName BUSY, PinName RESET, int frequency) : _spi(NC, MISO, SCLK), _cs(CS), _convst(CONVST), _busy(BUSY), _reset(RESET) {    
    _spi.frequency(frequency);
    _spi.format(8, 0);
    _cs = 1;
    _convst = 1;
    _reset = 0;
    _q = 0.0;
    reset();
};

// Resets the AD7606
void AD7606::reset() {
    _reset = 1;
    _reset = 0;
}

// Computes and stores the quantization step of the AD7606 as a function of its dynamic range (10 V or 20 V)
void AD7606::setDR(double DR) {
    _q = (double) DR/65535.0; // Quantization step
}
    
// Read raw values from all 8 channels
// rawDataBuffer is a pointer to an array of 8 16-bit integers
void AD7606::readRAW(int16_t *rawDataBuffer) {
    uint8_t lowByte, highByte;

    _convst = 0; // Pulse CONVSTA/CONVSTB to start conversion
    _convst = 1;
    wait_us(5);   
    //while (_busy) {
        // wait for conversions to be completed (low level on BUSY)
    //}
    _cs = 0; // Enable DOUTA/DOUTB lines and shift-out the conversion results
    for (char k = 0;  k < 8; k++) {
        highByte = _spi.write(0x00);    
        lowByte = _spi.write(0x00);
        *(rawDataBuffer + k) = (int16_t) ((highByte << 8) + lowByte);    
    }   
    _cs = 1;
}

// Read analog values from all 8 channels
// analogDataBuffer is a pointer to an array of 8 doubles
void AD7606::readAnalog(double *analogDataBuffer) {
    uint8_t lowByte, highByte;
    
    _convst = 0; // Pulse CONVSTA/CONVSTB to start conversion
    wait_us(1);
    _convst = 1;
    wait_us(5);   
    //while (_busy) {
        // wait for conversions to be completed (low level on BUSY)
    //}
    _cs = 0; // Enable DOUTA/DOUTB lines and shift-out the conversion results
    for (char k = 0;  k < 8; k++) {
        highByte = _spi.write(0x00);    
        lowByte = _spi.write(0x00);
        *(analogDataBuffer + k) = (double) ((int16_t) ((highByte << 8) + lowByte))*_q;    
    }   
    _cs = 1;
}