This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS131M06: ADC SPI Communications Not Receiving Expected Results

Part Number: ADS131M06

According to the datasheet. To write to a register you send:
011A AAAA ANNN NNNN

So I put on my TX buffer: 0x6180, to write to CLOCK which has an address of 0x03h (according to the datasheet)
ie: 0110 0001 1000 0000

Making N 0 should not really affect anything here. When I do the MCSPI data transfer of 24 bits, I get in return 0x3fc7f8 (or other similar results) consistently.

Here is the code I used to send these messages:

void adcWriteReg(
                 unsigned short data, unsigned char wordLength, unsigned char size, MCSPI_Transaction spiTransaction) {
    int32_t             status = SystemP_SUCCESS;
    uint32_t            i;
    int32_t             transferOK;
    unsigned char shiftValue;

    if(wordLength == 16) {
        shiftValue = 0;
    } else if(wordLength == 24) {
        shiftValue = 8;
    } else if(wordLength == 32) {
        shiftValue = 16;
    } else {
    }

    // Setup Buffers
    gMcspiTxBuffer[0] = (data << shiftValue);
    gMcspiRxBuffer[0] = 0U;

    spiTransaction.count    = size / (gConfigMcspi0ChCfg[0].dataSize / APP_MCSPI_WORD);

    transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction);

    if((SystemP_SUCCESS != transferOK) ||
           (MCSPI_TRANSFER_COMPLETED != spiTransaction.status)) {
       DebugP_assert(FALSE); /* MCSPI transfer failed!! */
    } else {
        /* Print Data */
        for(i = 0U; i < size; i++) {
            DebugP_log("( %x -> %x )\n", gMcspiTxBuffer[i],gMcspiRxBuffer[i]);
        }
    }
}

...
adcWriteReg((WREG | CLOCK_ADDR), 24, 1, spiTransaction);
adcWriteReg(CLOCK_CH0_EN | CLOCK_OSR_1024 | CLOCK_PWR_HR, 24, 1, spiTransaction);
...

Perhaps its an error on the side of how MCSPI works, but I have setup everything correctly (to my knowledge):

4 pin mode, tx and rx, input on D1, tx enabled on d1, tx disabled on d0, transfer mode blocking, CS polarity (low), frequency 25MHz, data frame size (24)

Can anyone help me figure out how to send and receive data that I expect to see?

  • Hello Dylan,

    I agree that your high level assumptions for a write command are correct and good. I don't have familiarity for MCSPI but it looks like you're just configuring the settings for the SPI in HW and I don't see anything wrong there.

    I suggest you take a look at the example code https://www.ti.com/lit/zip/sbac254 . I've quickly looked over your code and don't see anything obvious. However, we can revisit after you see how the example code is written (which, in my opinion, is a bit easier to follow compared to this snippet of code).

    As a side question, have you verified that reads work? This is the purpose of the ID register (addr: 0x00), the space is read only and the top two bytes are known. I would recommend starting with reads before moving to writes if we're in the process of verifying the frame you are sending is in the right format. This means you'll have a foundation of success before moving onto changing the other parts of the SPI frame.

    Best,

    -Cole

  • Yeah I have looked through there stuff for a while and haven't found anything yet.

    Trying the read, I receive this output from the MCSPI transfer:

    ( a00000 -> 7f8ff1 )

    which is not what you would expect to get (doc says 0x26XX) but I test ran this 8 times and got the same message every time.

    Some further clarifications on how MCSPI works. Its a library build for certain CCS TI boards, in my case its the LP243AM.

    When you run MCSPI_transfer it essentially performs a write from the TX array for N elements and outputs onto the RX array, and sets the CS pin accordingly. Here is what the read code looks like. I am assuming the ADS by default is in 24 bit word length mode and have configured it as such. On my oscilloscope I have confirmed that the bit pattern sent on the TX and received in the RX is in the same order as printed above. 

    As for physical hardware, I have an 8.2MHz oscillator hooked up to the CLKIN pin, the RESET pin is tied to 3.3V, DVDD and AVDD is tied to the 3.3V, and AVGND and DVGND are tied to ground (the 3.3V and ground pins are supplied by my board). I left all of the AIN pins untied except AIN0_N which is tied to ground and AIN0_P is left unconnected (for now). I also have REFIN at 1.23V (using a voltage divider coming off of the 3.3V). 

    void adcReadReg( unsigned short addrMask,
                     unsigned char wordLength, unsigned char size, MCSPI_Transaction spiTransaction) {
        int32_t             status = SystemP_SUCCESS;
        uint32_t            i;
        int32_t             transferOK;
        unsigned char shiftValue = wordLength - 16; //Bits to shift based on size.
                                                    //for 24, we shift 8 bits to the left
    
        // Input Message onto buffer.
        gMcspiTxBuffer[0] = ((RREG | addrMask) << shiftValue);
        gMcspiRxBuffer[0] = 0U;
        
        //this is just how many array elements get transferred and roughly is just "size"
        spiTransaction.count    = size / (gConfigMcspi0ChCfg[0].dataSize / APP_MCSPI_WORD);
        
        //transferOK is a whether the thing is successful
        transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction);
        
        //This prints the TX and RX buffers
        if((SystemP_SUCCESS != transferOK) ||
               (MCSPI_TRANSFER_COMPLETED != spiTransaction.status)) {
           DebugP_assert(FALSE); /* MCSPI transfer failed!! */
        } else {
            /* Print Data */
            for(i = 0U; i < size; i++) {
                DebugP_log("( %x -> %x )\n", gMcspiTxBuffer[i],gMcspiRxBuffer[i]);
            }
        }
    }
    
    
    void *mcspi_loopback_main(void *args)
    {
        int32_t             status = SystemP_SUCCESS;
        uint32_t            i;
        int32_t             transferOK;
        MCSPI_Transaction   spiTransaction;
    
        Drivers_open();
        Board_driversOpen();
    
        DebugP_log("[ADS131M06] TX-RX example started ...\r\n");
    
        /* Memfill buffers */
        for(i = 0U; i < APP_MCSPI_MSGSIZE; i++)
        {
            gMcspiTxBuffer[i] = 0U;
            gMcspiRxBuffer[i] = 0U;
        }
    
        spiTransaction.args     = NULL;
        spiTransaction.txBuf    = (void *)gMcspiTxBuffer;
        spiTransaction.rxBuf    = (void *)gMcspiRxBuffer;
        spiTransaction.channel  = gConfigMcspi0ChCfg[0].chNum;
        spiTransaction.count    = REG_MCSPI_MSGSIZE / (gConfigMcspi0ChCfg[0].dataSize / APP_MCSPI_WORD);
    
        // Delay because we aren't reading DRDY
        ClockP_sleep(1);
    
        /* Read from ID (hex is just zeros for A) */
        adcReadReg(0x0000, 24, 1, spiTransaction);
    
        // Delay because we aren't reading DRDY
        ClockP_sleep(1);
    
        Board_driversClose();
        Drivers_close();
    
        return NULL;
    }

  • Hello Dylan,

    Unfortunately, I have some conflicting assumptions that I need to confirm with you. According to the datasheet we have multiple words in a frame:

    I'm assuming your word size is 24 bits, as that's what your response is. And we will have 8 words of data.

    Or illustrated in the case of a single write where all the channel data, and CRC (or zeros if disabled) until we can grab the register data:

    Now, the interesting bit comes from the text where we expect 0x00 padded LSB words in the case of a reading the word that contains the register read result:

    Your response has some 1b's present in the last 8 bits and LSB so I cannot be sure you're reading the word that holds register data. My guess is that you're reading immediately after the command finishes, and as a result, reading channel 0 data. I would have thought the spiTransaction.count would have been counting 8 frames later but I don't see anything like that as it seems to be purely based on the word size, and not including the entire frame.

    Even if an invalid command is sent, it would be processed as a null, so we would still see zero padded 0x00 on the LSB.

    Let me know what you think.

    Best,

    -Cole

  • Yeah I read that section, I was trying to take advantage of the short spi communication to do settings based things but all the channels need to be off. Anyways so I send the read message + a bunch of zeros and I also set nnnnnnnn = 1 so it may send me the data one message later, and got:
    ( a00100 -> 7f8ff1 )
    ( 0 -> fe3fc7 )
    ( 0 -> f8ff1f )
    ( 0 -> e3fc7f )
    ( 0 -> 8ff1fe )
    ( 0 -> 3fc7f8 )
    ( 0 -> ff1fe3 )
    ( 0 -> fc7f8f )

    ( a00100 -> 7f8ff1 )
    ( a00100 -> fe3fc7 )
    ( a00100 -> f8ff1f )
    ( a00100 -> e3fc8f )
    ( a00100 -> f1fe3f )
    ( a00100 -> c7f8ff )
    ( a00100 -> 1fe3fc )
    ( a00100 -> 7f8ff1 )

    alternatively, where nnnnnnnn = 0:

    ( a00000 -> 7f8ff1 )
    ( 0 -> fe3fc7 )
    ( 0 -> f8ff1f )
    ( 0 -> e3fc7f )
    ( 0 -> 8ff1fe )
    ( 0 -> 3fc7f8 )
    ( 0 -> ff1fe3 )
    ( 0 -> fc7f8f )

    ( a00000 -> 7f8ff1 )
    ( a00000 -> fe3fc7 )
    ( a00000 -> f8ff1f )
    ( a00000 -> e3fc7f )
    ( a00000 -> 91fe3f )
    ( a00000 -> c7f8ff )
    ( a00000 -> 1fe3fc )
    ( a00000 -> 7f8ff1 )

    Interestingly enough all input variations resulted in roughly all the same outputs. the first message output being always the same.

  • Hello Dylan,

    To get into short SPI Communication, to disable all the channels (CHx_EN) through the clock registers (overwriting the default from 1b to 0b), as you said. I don't think we've verified if you've ever successfully written to the device so I'm not sure I can make the assumption that it worked. Normally, a customer will have an initialization routine to utilize short SPI Communication. 

    Interestingly enough, it looks like your follow up was supposed to compensate for that but it still doesn't make any sense. They don't align with realistic data, (somewhere between -100mV or almost 2.8V) and they don't align with any obvious register space.

    At this point, I'd like to see a logic analyzer or multi-channel oscilloscope screenshot that illustrates the timing for DOUT, DIN, SCLK, and CS for a read command; reading the ID register should be fine. Having the signals in isolation won't work (i.e. we need to trigger off CS and checking out the first and second word).

    If we both agree the device should be experiencing the right commands, as you've said previously, then we'll have to start looking at hardware to see if anything is wrong.

    Best,

    -Cole

    Edit: just clarifying for other readers

  • Yeah I think it may be a hardware thing. I ordered a new adapter: https://www.amazon.com/gp/product/B07MYMX1QS/ that should hopefully let me put a new chip in without wasting it (ie soldering it). The pinouts from the oscilloscope are not great. Here are some pics, but tldr the data out pin seems to be outputting a lower voltage than it should and CS pin has a long LONG delay before it begins suing the SCKL. I recorded these with a 1GSa/s or 200MHz oscilloscope so the readings aren't going past my sample time.

    MOSI (yellow), MISO (purple). V per Div on both channels is 1V/div. MOSI seems to give me 3.3V message but MISO seems to only hit 1.25V?

    MOSI(yellow) SCK (purple). Strangely enough the clock signal appears to go between 2.5V and 0.8V, I don't know if its something with the LPam243 but maybe this is fine.

    (zoomed in from above on first 24 bits)

    This is the interesting thing. MISO (yellow) SCKL (purple)

    (zoomed in above) Most interesting thing here is my CCS printed 0's for all messages but the ADS printed this pattern for all messages. Still not a meaningful pattern to us, but interesting to note that there are disparities.

    And finally CS (yellow), SCKL (purple) just showing that the chip select works although the chip select does seem to have a long time after it pulls down before the SCKL begins, which may be screwing with us.

  • Hi Dylan -  I will try to help while Cole is out of the office.

    Beginning with your last point, the delay between CSn falling edge and the first SCLK rising edge is determined by your host controller. From the ADC's perspective, it is not a problem to have this delay (in fact - not having enough delay often causes problems).

    With regards to SCLK, I am more concerned with the average high and low levels observed when SCLK is being driven. As you can see, SCLK only seems to toggle between about 800 mV and 2.4 V. However, the device expects a logic low voltage no greater than 0.2*DVDD = 660 mV. Similarly, the expected logic high voltage is at least 2.64 V or greater. Between the minimum logic high level and maximum logic low level, the ADC may miss some of the SCLKs. Is it possible that another device or circuit component is loading your SCLK signal? Is there anything you can remove (i.e. pull-up or series resistors)?

    Regards,

    Ryan

  • I totally agree, the SCK is a big problem. I am using the LPAM243X and nothing is connected to the pin besides the ADC's pin. I will perform some tests and see if I can fix that otherwise I will post something in the LPAM243X forum about it. I also was interested as to why the MISO signal is very low voltage, is that normal? Would the SCK being wrong affect that?

  • Hi Dylan,

    The MISO output pin is not be affected by the SCLK amplitude. However, similar to SCLK, if something is loading the output and drawing excessive current, internal circuit driving that pin may have trouble producing the correct voltage values. You'll notice in the Electrical Characteristics table that V_OL and V_OH are measured while drawing ~ 1 mA (see Test Conditions). It's not stated how much more current those pins can source before the voltage droops.

    It's difficult to tell exactly what MISO and SCLK are doing in some of the pictures. Could you try to capture one image with SCLK and MISO for only 24 clocks (i.e. one output word if you're using the 24-bit word size)?

    Also, do you have a picture of your PCB setup and a schematic that you can share? 

    Regards,

    Ryan

  • Maybe I should make the pin for the MISO pulldown? This is a rough schematic, right side is pins 17 to 32. Although the resistors and capacitors are not currently connected. Pretty much the MISO is plugged directly from the DOUT to the pin on the LPAM243 for data input. It could just be a current source issue, in that I am powering the ADC from the 3.3V on my LPAM243X, perhaps it cannot supply enough current for the board to output a strong enough signal for the DOUT? I have also found that the SCKL voltage is the same way when not connected to anything, so at least that is a LPAM243X problem.

  • Hi Dylan,

    Thanks for sharing. Maybe one thing you can try is to separate the ADS131M06 supply from the LPAM243X supply. Use an external bench power supply to provide 3.3 V to AVDD and DVDD (pins 15 and 26, respectively). Do you have the ability to disconnect the +3.3V supply from the ADC circuit and flywire an external supply? Make sure to also share the GND connection between the ADC and the external supply as well.

    Regards,

    Ryan

  • Yeah, I am contacting your group that does the LPAM243 about the clock stuff but I am probably going to run a comparator to my bad clock signal to clean it up and try an external power supply if that alone doesn't fix the issues. The power pins on my printed schematic board are easily accessible, I just need to setup my lab bench.

  • Hello Dylan,

    Any luck with the external supply?

    For some advice in future debugs, whenever your digital IO voltage rail pulls down like an RC filter, you should be wary that the supply is reaching some sort of current limit, which means it cannot keep a constant voltage (and you can swap to an external supply that can supply the current), or the pull up resistors used on open-drain IOs might be too low in resistance, which means the resistors pull too much current from the supply (and the resistor's value can be increased).

    When you see these dips in a periodic pattern, you need to find the signal that lines up with those. In this case, it seem very periodic so I'd expect SCLK as the either coupling or contributing inductive kick back on GND. This inductive kick back essentially causes the GND, which should be 0V, to wiggle around and not stay a constant 0V. In this case, if you see 100s of mV dipping below GND, you have to acknowledge that's not normal behavior. Reducing inductance in GND path is usually done with layout, but thicker wires, more wires, or wires closer to the supply pin of the ADC or device can help fix this problem.

    Best,

    -Cole

  • The SCKL from the LPAM243 is just broken somehow. I don't have another board to tell if its a problem with my board or with their design, but the waveform is properly scaled at 1MHz, just not the 25MHz needed for this ADC. I am currently working on getting a schmitt trigger in order to properly scale the clock, so it will take me some time before I figure out the problem with the MISO signal. I'll make another thread when I get the SCKL properly scaled, thanks for the advice.