0
\$\begingroup\$

I have tried to communicate with this device with no success. Anybody have any tips. Or has anybody successfully worked with it. I implemented until now just a read and write function and the psuedo code here under.

Table XX. Pseudo-Code for Setting Up AD7730 for Continuous Conversion and Continuous Read Operation

  • Write 02 Hex to Serial Port /* Writes to Communications Register Setting Next Operation as Write to Mode Register*/
  • Write 2180 Hex to Serial Port /* Writes to Mode Register Starting Continuous Conversions for 0 mV to +10 mV Input Range*/
  • Write 21 Hex to Serial Port /* Writes to Communications Register Setting Next Operation as Continuous Read From Data Register*/
  • Set DIN Line of AD7730 Low /* Ensures Part is not Reset While in Continuous Read Mode*/
  • READ_DATA: Wait for RDY Low /* Wait for RDY pin to go low to Indicate Output Update*/
  • Read 24-Bit Data From Serial Port /* Read Conversion Result from AD7730's Data Register*/
  • Loop to READ_DATA Until All Data Gathered
  • Write 30 Hex to Serial Port /* Ends Continuous Read Operation and Places Part in Mode Where It Expects Write to Communications Register*/

My read and write code:

unsigned long AD7730_readRegistry(uint8_t regAddress, int bytes)
{
    uint8_t data[5] = {0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned long receivedData = 0x00;
    
    data[0] = CR_SINGLE_R | AD7730_COMM_ADD(regAddress);
    spi_write(data[0]);
    spi_read(data, bytes);
    
    if(bytes == 3){
        receivedData += ((unsigned long)data[0] << 16);
        receivedData += ((unsigned long)data[1] << 8);
        receivedData += ((unsigned long)data[2]);
    }
    if(bytes == 2){
        receivedData += (data[0] << 8);
        receivedData += (data[1]);
    }
    if(bytes == 1){
        receivedData += (data[0]);
    }
    return receivedData;
} 

void AD7730_writeRegistry(uint8_t regAddress, uint32_t regValue, int bytes)
{
    uint8_t data[5] = {0x00, 0x00, 0x00, 0x00, 0x00};
        
    data[0] = CR_SINGLE_W | AD7730_COMM_ADD(regAddress);
    if(bytes == 3){
        data[3] = ((regValue  & 0x0000FF));
        data[2] = ((regValue >> 8) & 0x00FF00);
        data[1] = ((regValue >> 16) & 0xFF0000);
    }
    if(bytes == 2){
        data[2] = ((regValue & 0x0000FF));
        data[1] = ((regValue >> 8) & 0x00FF00);
    }
    if(bytes == 1){
        data[1] = regValue;
    }
    for(int i = 0; i < bytes; i++){
         spi_write(data[i]);
    }
}

int main(void)
{
    Config32MHzClock_Ext16M();
    
    init_stream(F_CPU);
    AD7730_spi_init();
    AD7730_hardwareReset();
    sei();
    
    AD7730_writeRegistry(AD7730_MODE_REG, 0x2180, 2);
    AD7730_writeRegistry(AD7730_DATA_REG, CR_START_CONT, 1);
    PORTD.OUTCLR = SPI_MOSI_bm;
    
    while (1) 
    {   
        AD7730_readRegistry(AD7730_DATA_REG, 3);
        AD7730_WaitReady();
    }
}

Datasheet: AD7730/AD7730L

These two functions set the device in the whatever mode and continuous read.

//Write specific mode
void AD7730_SetMode(unsigned short modeOperation, unsigned char    nputRange,  unsigned char channel)
{
    unsigned short oldRegisterVal = 0x0;
    unsigned short newRegisterVal = 0x0;

    oldRegisterVal = AD7730_GetRegisterValue(AD7730_COMM_ADDR(AD7730_REG_MODE), 2);
    newRegisterVal = oldRegisterVal & ~(AD7730_MODE_SEL(0x07) | AD7730_MODE_RANGE_SEL(0x03) | AD7730_MODE_CHANNEL_SEL(0x03));
    newRegisterVal = newRegisterVal | modeOperation | inputRange | channel;
    AD7730_SetRegisterValue(AD7730_COMM_ADDR(AD7730_REG_MODE), newRegisterVal, 2);
}

//Returns avg of several conversion
unsigned long AD7730_ContinuousReadAvg(unsigned char channel, unsigned char inputRange, unsigned char sampleNumber)
{
    unsigned char registerWord[4] = {0};
    unsigned long samplesAverage = 0;
    unsigned char count = 0x00;

    AD7730_SetMode(AD7730_MODE_SEL(AD7730_MODE_CONT_CONV), inputRange, channel);
    registerWord[0] = 0x01;
    registerWord[1] = AD7730_COMM_RW(AD7730_COMM_START_CONT_RD) | AD7730_COMM_ADDR(AD7730_REG_DATA);
    spi_write(registerWord, 1);

    for(count = 0; count < sampleNumber;count ++)
    {
        registerWord[0] = 0x01;
        registerWord[1] = 0x0;
        registerWord[2] = 0x0;
        registerWord[3] = 0x0;
        AD7730_WaitReady();
        spi_read(registerWord, 3);
        samplesAverage += ((unsigned long)registerWord[0] << 16) + ((unsigned long)registerWord[1] << 8) + registerWord[2];
    }
    samplesAverage = samplesAverage / sampleNumber;
    registerWord[0] = 0x01;
    registerWord[1] = AD7730_COMM_RW(AD7730_COMM_STOP_CONT_RD) | AD7730_COMM_ADDR(AD7730_REG_COMM);
    spi_write(registerWord, 1);

    return(samplesAverage);
}

Playing around with the code reading the signals on an oscilloscope. An issue that I notice during a single read is that the ready output does not pulse or signal that data is ready to be read. I'll keep posting updates.

oscilloscope

\$\endgroup\$
9
  • 2
    \$\begingroup\$ I would be suspicious of clock polarity; it is settable on the device and you need to make sure your code matches that. SPI interfaces are notorious for having clock polarity and phase issues. The datasheet goes into quite some detail - see page 8 \$\endgroup\$ Commented Aug 1, 2018 at 14:29
  • \$\begingroup\$ No, the Analog Devices engineers decided that entire testing business was overrated and just went from schematic to selling the silicon. \$\endgroup\$
    – Joren Vaes
    Commented Aug 1, 2018 at 14:32
  • 1
    \$\begingroup\$ @JorenVaes in fact, they also realized that if they do that, they can make the chip much cheaper by always letting it produce the same output. </sarcasm> \$\endgroup\$ Commented Aug 1, 2018 at 14:33
  • 1
    \$\begingroup\$ so, what about "AD7730: Can't communicate via SPI"? That would describe the problem you're having instead of asking a rhetorical question. \$\endgroup\$ Commented Aug 1, 2018 at 14:40
  • \$\begingroup\$ This is a Burr Brown special that has since been bought by analog. Here is the cheat code: This isn't "real SPI", the mode is different between read and write commands (flip clock phase) \$\endgroup\$
    – crasic
    Commented Aug 1, 2018 at 16:42

1 Answer 1

1
\$\begingroup\$

1) AD7730_writeRegistry for 2 byte long data puts bytes into [2],[3]. If I am not mistaken, that should be [1] and [2]

2) AD7730_writeRegistry(AD7730_DATA_REG, CR_START_CONT, 1); This does not make sense.

First, the continuous read is set by writing 21 into Communications Register, not into Data register. Your function AD7730_writeRegistry always writes CR_SINGLE_W (i.e. single write) into Communications register.

Second, you have to decide whether you use continuous or single read. In continuous read you cannot do anything else but reading the same register over and over again. And you cannot use your AD7730_readRegistry for this, because it tries to write into comm register on each call.

Third, the wait for RDY line should be before the read in the loop, not after. Otherwise you will be reading invalid data.

Fourth, I am not sure PORTD.OUTCLR is sufficient to keep MOSI line low, as recommended for continuous read operation. I suspect next call to spi_read will start clocking out the last transmitted byte. Hopefully it will be the same "start cont read data register" command, so it should not reset the AD7730.

\$\endgroup\$
2
  • \$\begingroup\$ Yeah that is correct on the DATA_REG, also rewritting my code to use interrupt to send more bytes instead of using array and for loops. Yeah, the continuous mode is confusing me at the moment. Cause you still need to do a single write to the registers. \$\endgroup\$
    – user161991
    Commented Aug 1, 2018 at 17:43
  • \$\begingroup\$ "Cause you still need to do a single write to the registers" No, you don't. Once you've switched to continuous read mode you do not write anything, you keep reading (by sending clock). You only write 30 into Comm to exit continuous mode. That is why you are setting MOSI to permanent 0, until you have to transmit that "30" \$\endgroup\$
    – Maple
    Commented Aug 1, 2018 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.