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.

ADS125H01: ADS125H01 CRC Problem

Part Number: ADS125H01
Other Parts Discussed in Thread: ADS125H02

Tool/software:

Hi!
I'm using the ADS125H01 with an STM32H745. 

I have converted the library that is provided to the stm32 and setup SPI. 

My SPI setup is:

I am executing 

adcStartupRoutine();

startConversions();

After I have setup the SPI and all the peripherals. 

My adcStartupRoutine looks like this:

void adcStartupRoutine(void)

{

/* (OPTIONAL) Provide additional delay time for power supply settling */

HAL_Delay(50);

/* (REQUIRED) Set nRESET pin high for ADC operation */

setRESET();

/* (OPTIONAL) Start ADC conversions with HW pin control.

* NOTE: Using the HW pin control here to monitor the nDRDY falling edge.

*/

setSTART(HIGH);

/* (REQUIRED) NO SPI COMMANDS ARE ALLOWED PRIOR TO nDRDY RISING EDGE!

* In case the MCU cannot monitor the nDRDY rising edge during startup,

* for example if the MCU is performing other startup tasks at this time,

* use the nDRDY falling edge as the indicator that the device is ready

* for communication as is done here.

*

* Alternatively, insert a 100 ms delay here if nDRDY pin is not monitored.

* NOTE: Default data rate is 20 SPS => 50 ms conversion period.

*/

pollForDRDY(100);

/* (OPTIONAL) Start ADC conversions with the SPI command.

* This can occur any time after the nDRDY rising edge,

* but is not needed if the START pin has already been set HIGH.

*

* sendCommand(START_OPCODE);

*/

// sendCommand(START_OPCODE);

/* (OPTIONAL) Toggle nRESET pin to assure default register settings. */

/* NOTE: This also ensures that the device registers are unlocked. */

// toggleRESET();

// unlockRegisters();

/* (OPTIONAL) Configure initial device register settings here */

uint8_t initRegisterMap[NUM_REGISTERS];

initRegisterMap[REG_ADDR_ID] = 0x00; /* NOTE: This a read-only register */

initRegisterMap[REG_ADDR_STATUS0] = STATUS0_CLEAR; /* NOTE: This a non-default setting */

initRegisterMap[REG_ADDR_MODE0] = MODE0_DEFAULT;

initRegisterMap[REG_ADDR_MODE1] = MODE1_DEFAULT;

initRegisterMap[REG_ADDR_MODE2] = MODE2_DEFAULT;

initRegisterMap[REG_ADDR_MODE3] = MODE3_DEFAULT;

initRegisterMap[REG_ADDR_REF] = REF_DEFAULT;

initRegisterMap[REG_ADDR_OFCAL0] = OFCAL0_DEFAULT;

initRegisterMap[REG_ADDR_OFCAL1] = OFCAL1_DEFAULT;

initRegisterMap[REG_ADDR_OFCAL2] = OFCAL2_DEFAULT;

initRegisterMap[REG_ADDR_FSCAL0] = FSCAL0_DEFAULT;

initRegisterMap[REG_ADDR_FSCAL1] = FSCAL1_DEFAULT;

initRegisterMap[REG_ADDR_FSCAL2] = FSCAL2_DEFAULT;

initRegisterMap[REG_ADDR_IMUX] = IMUX_DEFAULT;

initRegisterMap[REG_ADDR_IMAG] = IMAG_DEFAULT;

initRegisterMap[REG_ADDR_RESERVED] = RESERVED_DEFAULT;

initRegisterMap[REG_ADDR_MODE4] = MODE4_GAIN_0P25;

initRegisterMap[REG_ADDR_STATUS1] = STATUS1_CLEAR; /* NOTE: This a non-default setting */

initRegisterMap[REG_ADDR_STATUS2] = STATUS2_CLEAR; /* NOTE: This a non-default setting */

/* (OPTIONAL) Write to all registers */

writeMultipleRegisters(REG_ADDR_ID, NUM_REGISTERS, initRegisterMap);

/* (OPTIONAL) Read back all registers */

// readMultipleRegisters(REG_ADDR_ID, NUM_REGISTERS, NULL);

/* (OPTIONAL) Check STATUS register for faults */

// pollForDRDY(100); /* Avoids data not new STATUS flag */

uint8_t status_register = readSingleRegister(REG_ADDR_STATUS0);

printf("Status register %d\r\n", status_register);

}

I have changed the gain to 0.25 as I have an input of up to 10V.

The problem is the following. 

I am getting an error when validating the SPI message. The error is that the [2] (3rd element) of the Tx Buffer and the [3] (4th element) of the Rx Buffer do not match when the ADC sends back the result. 
Example:

81 - 255
0 - 81
215 - 0
0 - 49
Not 4
SPI Error!

[0] - 81 TXBuffer; For [0] the ADC returns 255, thus 0xff which is good. 

[1] - 0 TX; ADC returns [0] of the TX; which is 81 which is good...

[2] same story, everything okay. 

[3] here is where it doesn't work, as for every message I send, I get a different CRC value than the ADC returns. 

The CRC generating code looks like this (from the library provided by TI)

uint8_t calculateCRC(const uint8_t dataBytes[], uint8_t numBytes)

{

/* Check that "numBytes" is between 1 and 4 */

assert((numBytes >= 1) && (numBytes <= 4));

/* Check that "dataBytes" is not a null pointer */

assert(dataBytes != NULL);

/* NOTE:

* Using "uint_fast8_t" types here instead of "uint8_t" to avoid unnecessary

* implicit type conversions. Reference this E2E thread for additional info:

* e2e.ti.com/.../679200

*/

uint_fast8_t crc = 0xFFu; /* Initial value of crc register */

bool crcMSb; /* Most significant bit of crc byte */

uint_fast8_t poly = 0x07u; /* CRC polynomial byte */

uint_fast8_t shift_by = 0u; /* Intermediate variable */

uint32_t data = 0u; /* Data storage variable */

uint32_t msbMask = 0x80000000u; /* Points to the next data bit */

bool dataMSb; /* Most significant bit of data int */

/* Construct data word from data bytes */

uint_fast8_t i;

for (i = 0; i < numBytes; i++)

{

shift_by = 8 * (numBytes - i - 1);

data |= (((uint32_t) dataBytes[i]) << shift_by);

}

/* Determine the location of the first data byte */

shift_by = 8 * (4 - numBytes);

msbMask >>= shift_by;

/* CRC algorithm */

while (msbMask > 0)

{

// Check MSB's of data and crc

dataMSb = (bool) (data & msbMask);

crcMSb = (bool) (crc & 0x80u);

// Shift crc byte

crc <<= 1;

// Check if XOR operation of MSbs results in additional XOR operation

if (dataMSb ^ crcMSb) { crc ^= poly; }

/* Shift MSb pointer */

msbMask >>= 1;

}

return (uint8_t) (crc & 0xFF);

}

I am also using STM32 function for the SPI transmit and receive:

HAL_SPI_TransmitReceive(&hspi2, DataTx, DataRx, byteLength, 100);


I have also analyzed the protocol with an oscilloscope and the values I have pasted above I am reading on the oscilloscope also. 

Is it possible that the library crc check doesn't work properly?

Is my chip maybe damaged? 


All the best!

  • Hi Silard Gal,

    Can you please provide us logic analyzer data showing the complete communication, including CS1, CS2, SCLK, DOUT, DIN, and DRDY? This will help us better diagnose your issue as we will be able to see what you are sending to the ADC and how the ADC is responding. We can also verify timing, etc., that is not possible to do by just looking at the code

    -Bryan

  • Here is the startup. This is when the board gets power. 
    CS1, CS2, RESET is pulled up. 

    Zoomed in. When nDRDY pin goes low, the controller initiates a read command. 

    I have experimented with two commands. The NOP and the read command with combined status0 and adc values. 

    This is the NOP command. I have managed to get that to work, as it returns good CRC. 


    This is with the Read command. 

  • One more thing I would add is that I am not:

    - sending configuration to use external reference

    - setting up gain to be 0.25 

    - setting up FIR and low speed sampling

  • Hi Silard Gal,

    It is interesting that the CRC algorithm gives you the correct response sometimes and not others e.g. for the read command I calculate that CRC-2 should be 0xAA for 0x12 00 (the RDATA command + arbitrary byte). When you run through the code, this is not the output you are getting? Are you sure the input parameters are specified correctly? Again, it is odd that the code works for some inputs but not others - that does not make much sense

      -Bryan

  • I have hard coded 0xAA and it reads some data... will see to create my own crc function and to check everything else... 
    still it is very wierd that the function provided by TI is not working... 

  • An online compiler with the same function spits out the correct value (0xAA) where the same function on the mcu, spits out 0xFD. 

    The function is:

    uint8_t calculateCRC(const uint8_t dataBytes[], uint8_t numBytes)

    {

    uint8_t crc = 0xFF; /* Initial value of crc register */

    bool crcMSb; /* Most significant bit of crc byte */

    uint8_t poly = 0x07; /* CRC polynomial byte */

    uint8_t shift_by = 0; /* Intermediate variable */

    uint32_t data = 0; /* Data storage variable */

    uint32_t msbMask = 0x80000000; /* Points to the next data bit */

    bool dataMSb; /* Most significant bit of data int */

    /* Construct data word from data bytes */

    uint8_t i;

    for (i = 0; i < numBytes; i++)

    {

    shift_by = 8 * (numBytes - i - 1);

    data |= (((uint32_t) dataBytes[i]) << shift_by);

    }

    /* Determine the location of the first data byte */

    shift_by = 8 * (4 - numBytes);

    msbMask >>= shift_by;

    /* CRC algorithm */

    while (msbMask > 0)

    {

    // Check MSB's of data and crc

    dataMSb = (bool) (data & msbMask);

    crcMSb = (bool) (crc & 0x80u);

    // Shift crc byte

    crc <<= 1;

    // Check if XOR operation of MSbs results in additional XOR operation

    if (dataMSb ^ crcMSb) { crc ^= poly; }

    /* Shift MSb pointer */

    msbMask >>= 1;

    }

    return (uint8_t) (crc & 0xFF);

    }

  • Hi Silard Gal,

    Are you able to step through the CRC function on both the online compiler and the MCU to see where exactly the issue occurs? Maybe this will help illuminate what is causing the issue

    It sounds like the code on your MCU does work sometimes e.g. for NOP, but not all the time - is that correct?

    -Bryan

  • I didn't have the chance to reply here, but I got it working yesterday. 
    Yes, the problem was with the CRC function, but not relating to NOP.

    There is this part where it casts an operation into a boolean. 

    dataMSb = (bool) (data & msbMask);

    In my case, for some reason, bool was a "typedef int bool"... meaning that the dataMSb was floating between the ranges of an integer, thus making the crc output different. 

    I had to add #include <stdbool.h> and it all started working. 

  • Hi Silard Gal,

    Thanks for posting the resolution to your issue

    Yes, the ADS125H02.c includes a reference to the ADS125H02.h header filer, which includes the reference to <stdbool.h>

    If you imported both files into your project this should have worked fine; if you just copied the code for the CRC calculation, then I can see where this error might have occurred

    -Bryan