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.

CCS/ADS114S08EVM: How to communicate with ADS114S08EVM with external processor (TIVA TM4C129NCPD)

Part Number: ADS114S08EVM
Other Parts Discussed in Thread: ADS114S08, ADS114S08B, ADS124S08

Tool/software: Code Composer Studio

I use J3 on board to be able communicate with ADS114S08 through SPI. The external processor that I use is TIVA TM4C129NCPD. I use the RTD (3-WIRE one ) channel of the board and connected a resistor between AN1-AN2.

First, I initialized the SSI0 module executing InitSSI function as,  

void InitSSI(void)
{
uint32_t extra;

SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), SYS_CLK_FREQ);

SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

GPIOPinConfigure(GPIO_PA2_SSI0CLK); // SSI module 0 clock
GPIOPinConfigure(GPIO_PA3_SSI0FSS); // SSI module 0 frame signal
GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); // SSI Module 0 Bi-directional Data Pin 0 (SSI0TX in Legacy SSI Mode).
GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); // SSI Module 0 Bi-directional Data Pin 1 (SSI0RX in Legacy SSI Mode).

GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);

SSIConfigSetExpClk(SSI0_BASE, SYS_CLK_FREQ, SSI_FRF_MOTO_MODE_1, SSI_MODE_MASTER, 10000000, 8);

SSIEnable(SSI0_BASE);

while(SSIDataGetNonBlocking(SSI0_BASE, &extra)){ }
}

With settings above I was able to send data to the ADS114S08  succesfully. To initialize the ADS114S08 I executed Init_ADS114S08_RTD function as,

//*******************************************************
// ADS114S08B Definitions
//*******************************************************
#define RTD_START_COMMAND 0x08       // SPI data to start new conversion in ADS114S08
#define RTD_CH1_INPUTMUX 0x12           // SPI data to set AIN1 and AIN2 as positive and negative input selections, respectively.
#define RTD_CH1_IDACMUX 0x35             // SPI data to set AIN5 and AIN3 as excitation current of IDAC1 and IDAC2, respectively.

#define RTD_IDACMAG 0x07                     // SPI data to set IDAC magnitude to 1 mA.
#define RTD_PGA 0x0A                              // SPI data to set PGA to 4.
//#define RTD_DATARATE 0x3B                 // SPI data to set the clock source as internal (4.096 MHz), conversion more as single-shot, and data rate as 1000SPS
#define RTD_DATARATE 0x14                   // SPI data to set the clock source as internal (4.096 MHz), conversion more as single-shot, and data rate as 1000SPS
#define RTD_REF 0x06                              // SPI data to enable positive buffer and disable negative buffer and to set REFP1-REFN1 as ref input.

#define RTD_RDATA_COMMAND 0x12     // RDATA command to read conversion data
#define RTD_WREG_COMMAND1 0x42    // WREG command to write the 6 device register data starting with INPMUX
#define RTD_WREG_COMMAND2 0x05

void Init_ADS114S08_RTD(void)
{
//
// Local variables
//
uint32_t dataRx;

//
// Send N bit data using the "blocking" put function (N = 16 bit as SSI configured so with SSIConfigSetExpClk function).
// This function will wait until there is room in the send FIFO before returning.
// This allows you to assure that all the data you send makes it into the send FIFO.
//

SSIDataPut(SSI0_BASE, 0x42);
SSIDataPut(SSI0_BASE, 0x05);
SSIDataPut(SSI0_BASE, RTD_CH1_INPUTMUX);
SSIDataPut(SSI0_BASE, RTD_PGA);
SSIDataPut(SSI0_BASE, RTD_DATARATE);
SSIDataPut(SSI0_BASE, RTD_REF);
SSIDataPut(SSI0_BASE, RTD_IDACMAG);
SSIDataPut(SSI0_BASE, RTD_CH1_IDACMUX);

while(SSIBusy(SSI0_BASE)){} // Wait until SSI0 is done transferring all the data in the transmit FIFO.

// Empty the garbage data in receive FIFO

SSIDataGet(SSI0_BASE, &dataRx);
SSIDataGet(SSI0_BASE, &dataRx);

SSIDataPut(SSI0_BASE, RTD_START_COMMAND); // start the initial conversion
while(SSIBusy(SSI0_BASE)){}

// Empty the garbage data in receive FIFO
SSIDataGet(SSI0_BASE, &dataRx);
}

The picture below is from our logic analyzer. As clearly seen although master sends the data the slave always sends 0x00. Well, initially I thought this is garbage data so I can ignore it knowing the fact that I should empty my receive FIFO anyhow. For that I executed SSIDataGet twice as it can be seen above to empty receive FIFO (Note: here I assumed SSIDataGet function will empty two FIFOs by reading 32 bits, pelase correct me if I am wrong). But, when I executed only the first one the function started waiting. Well, we expect this if receive FIFO is empty so that I checked SSI_SR_RNE register and realized that it stays always zero even after executing the SSIDataPut eight times. It sounds the receive FIFO does not get anything from the slave. 

Well, I ignored that and executed the following part in the main loop to read data from the slave:

SSIDataPut(SSI0_BASE, Dummy_word);
SSIDataPut(SSI0_BASE, RTD_RDATA_COMMAND); // SPI (RTD_RDATA_COMMAND) data to request AIN1 - AIN2 value from ADS114S08
SSIDataPut(SSI0_BASE, Dummy_word);
SSIDataPut(SSI0_BASE, Dummy_word);

while(SSIBusy(SSI0_BASE)){} // Wait until SSI0 is done transferring all the data in the transmit FIFO.

SSIDataGet(SSI0_BASE, &dataRx);

result = dataRx & 0xFFFF; // Capture the the least significant 16-bit data after the second reading.

I executed SSIDataPut four times hoping that last receive FIFO register will have valid data so that I can easily read it. After evaluating the read data I execute the following part for next reading 

// Start the conversion for next reading

SSIDataPut(SSI0_BASE, RTD_START_COMMAND);
while(SSIBusy(SSI0_BASE)){}
SSIDataGet(SSI0_BASE, &dataRx); // Ignore the result

 

As it can be seen, the last 16 bit is always zero which does not make sense to me. I also attached the picture of my setup. Any advice on this problem? Thanks in advance...

 


  • Hi Fatih,

    There are actually a number of issues. The largest issue is in the way you are using the SS (or CS) pin. This pin must be held low throughout the entire communication transaction. For your WREG command the CS must stay low and not toggle from the start of the command through to the last register written. From the Saleae shot it shows CS high then low then the 6 registers of data. Because the lengths of data can vary it is best to not use the built-in peripheral SS (or CS) pin, but rather control this pin manually in code using a GPIO. I also recommend using byte transfers as opposed to 16-bit transfers.

    Second issue is we recommend using 0x00 as NOP in the communication as opposed to 0xFF for dummy data transmitted. Also, as I stated earlier, byte transfers tend to work better as for the RDATA command only 3 bytes are required to be sent as opposed to 4. Most likely the data is showing as 0x00 because the WREG was not written correctly.

    Another issue, is you have commented that negative reference buffer is bypassed, but the value you are writing is 0x06 and should be 0x16.

    I would suggest reading back the register contents after you have written them to verify the contents have changed correctly. I would also suggest monitoring DRDY after the START command and wait until the conversion has been completed (DRDY transitions from high to low state) before attempting to read the result. Also, the result will be in binary 2's complement. Make sure that you handle the data correctly as the value is signed.

    Best regards,
    Bob B
  • Hi Bob,

    I see your point. Actually, I rerun the Init_ADS114S08_RTD I got the following results. It looks like that problem is solved. Regarding CS control, I was thinking that SSIDataPut function controls it. If I execute SSIDataPut function consecutively CS must always stay low right as now we observe in my new results below. Regarding the size of data transfer, The good thing about the SSIDataPut is that it automatically take CS to high after the last bit transfer is completed. I cannot visualize the control of CS with GPIO while also executing SSIDataPut function. That would be great if you clarify that. I already set up it to byte transfer with SSIConfigSetExpClk(SSI0_BASE, SYS_CLK_FREQ, SSI_FRF_MOTO_MODE_1, SSI_MODE_MASTER, 10000000, 8);. What made you think that it is 16bit transfer?



    I changed the dummy word to 0x00 based on your suggestion. I believe I do have byte transfer already. The reason why I sent 4 bytes was to extract the valid data easily. Lets suppose I do send the following and assuming that receive FIFO is empty (which I am not sure because I do not know how many times I was supposed to execute SSIDataGet after WREG commands)

    SSIDataPut(SSI0_BASE, RTD_RDATA_COMMAND); // SPI (RTD_RDATA_COMMAND) data to request AIN1 - AIN2 value from ADS114S08

    SSIDataPut(SSI0_BASE, Dummy_word);

    SSIDataPut(SSI0_BASE, Dummy_word);

    The ADS114s08 will send me one byte garbage data then 16 bit valid data as DATA1 and DATA2. Since FIFO register is 16 bits, one byte garbage data and DATA1 will be together  in one receive FIFO and the DATA1 will be in another receive FIFO register. I just send a dummy word initially to push the DATA1 and DATA2 to be in the same FIFO register so that I can easily read it. Please correct me if my thinking process is wrong. It could be wrong because I am not exactly sure how  SSIDataGet works.

    Lets suppose that the first two receive FIFO register is full. If I execute SSIDataGet(SSI0_BASE, &dataRx); does it read both receive FIFO registers and assign the value to the dataRx? Or it is reading only one receive FIFO at a time?

    Regarding  negative reference buffer, that was a mistake on commenting.

    The result is handled by the following code

    //

    // Check the MSB first and then convert digital code to RESISTANCE

    //

    if ( (result & 0x8000) == 0x8000 )

    {

    result = ~(result - 1); // Subtract 1 and complement the result

    RTD_Res = ( -2 * RREF * result / PGA ) / (65535) ; // in which 65535 = (2^16 - 1) Note to myself: we need to change this since we have different configuration.

    }

    else

    {

    RTD_Res = ( 2 * RREF * result / PGA ) / (65535) ; // in which 65535 = (2^16 - 1)

    }

    Actually, Saleae shot channel 4 shows the DRDY. I will check that and give enough time for data conversion as you suggested. Actually when I start the conversion I do execute a delay right after that as

    SSIDataPut(SSI0_BASE, RTD_START_COMMAND);

    while(SSIBusy(SSI0_BASE)){}

    SSIDataGet(SSI0_BASE, &dataRx);

    SysCtlDelay(ADS114S08_DELAY); // Delay a bit (~1.3ms) for conversion to be completed

     

    But it looks like DRDY is always high in my run and read data from slave is still 0x00 even after I applied your suggestions.

     

  • Hi Fatih,

    Make sure the RESET pin is high. You should be controlling this pin as there is nothing driving this when the level shifters are disabled. Yo can tie it high or use GPIO to control.

    You may also see some odd behavior due to the floating START/SYNC pin as well, so either tie high or low depending on how you want to operate the device.

    Also, to clear the receive buffer FIFO you should fetch a byte for every byte transmitted.

    Best regards,
    Bob B
  • "Also, to clear the receive buffer FIFO you should fetch a byte for every byte transmitted."

    To clear the receive buffer FIFO after executing the code below I should execute six SSIDataGet() right? Could you please elaborate how SSIDataGet() function works? Thanks in advance...

    //
    SSIDataPut(SSI0_BASE, 0x42);
    SSIDataPut(SSI0_BASE, 0x05);
    SSIDataPut(SSI0_BASE, RTD_CH1_INPUTMUX);
    SSIDataPut(SSI0_BASE, RTD_PGA);
    SSIDataPut(SSI0_BASE, RTD_DATARATE);
    SSIDataPut(SSI0_BASE, RTD_REF);
    SSIDataPut(SSI0_BASE, RTD_IDACMAG);
    SSIDataPut(SSI0_BASE, RTD_CH1_IDACMUX);
    //
  • I am asking more details regarding the SSIDataGet() because if I execute more than enough this function will wait until the receive buffer FIFO has new data... I am so confused with SSIDataGet() function?
  • As you suggested I tied both START and RESET pins to the GND as you can see from the setup picture below. Unfortunately, I still read zero from the ADS114S08. But again, DRDY is always HIGH even after I command START through SPI. Is not ADS114S08 supposed to start some conversion right after receiving START command even WREG is wrong?   

  • Hi Bob,

    I saw following statements earlier in one of discussions in TI forum:

    "If you call SSIDataPut(), followed by SSIDataGet(), followed by another SSIDataPut(), SSIDataGet(), you will discover that there will actually be a small gap in the transmission.  This gap can be eliminated by calling SSIDataPut(), SSIDataPut(), SSIDataGet(), SSIDataGet() instead.

    In practice, you can overlap reads and writes to accelerate the process.  For instance if you know that your command sequence to receive data requires 3 words to be sent, you can call SSIDataPut() 3 time, which will load up values into the FIFO so that they can be transmitted back-to-back, then you can call SSIDataGet() 3 times later to read out the dummy response data.

    If that is correct I should perform the initialization of the ADS114S08 as below. Please correct me if I am wrong?

    void Init_ADS114S08_RTD(void)

    {

    uint32_t dataRx;

    SSIDataPut(SSI0_BASE, RTD_WREG_COMMAND1);

    SSIDataPut(SSI0_BASE, RTD_WREG_COMMAND2);

    SSIDataPut(SSI0_BASE, RTD_CH1_INPUTMUX);

    SSIDataPut(SSI0_BASE, RTD_PGA);

    SSIDataPut(SSI0_BASE, RTD_DATARATE);

    SSIDataPut(SSI0_BASE, RTD_REF);

    SSIDataPut(SSI0_BASE, RTD_IDACMAG);

    SSIDataPut(SSI0_BASE, RTD_CH1_IDACMUX);

    while(SSIBusy(SSI0_BASE)){} // Wait until SSI0 is done transferring all the data in the transmit FIFO.

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataGet(SSI0_BASE, &dataRx);

    SSIDataPut(SSI0_BASE, RTD_START_COMMAND); // start the initial conversion

    while(SSIBusy(SSI0_BASE)){}

    SSIDataGet(SSI0_BASE, &dataRx);

    SysCtlDelay(ADS114S08_DELAY); // Delay a bit (~1.3ms) for conversion to be completed

    }

  • Hi Fatih,

    I primarily support the ADS124S08 and not Tiva so it is difficult for me to suggest something specific regarding the Tiva. As to Reset pin, I think you misunderstood. With Reset low, the device is held in a reset condition. This pin must be high to work. So set the Reset pin high, and then we can go from there if you are still having problems.

    Best regards,
    Bob B
  • Hi Fatih,

    As far as the SSIDataGet, if you are just trying to clear out any old data in the FIFO use the function SSIDataGetNonBlocking and defined in the SSI.c file in the TivaWare library. If there is no data in the FIFI, this function will return 0. You could use something like we use:

    while(SSIDataGetNonBlocking(SSI0_BASE, &junk)); // clear out junk data from the RX FIFO

    Best regards,
    Bob B
  • Hi Bob,

    Now, I am able to read the resistance value correctly. See me results below. The result is 0x4c94 and when I used in the following function

    RTD_Res = ( 2 * RREF * result / PGA ) / (65535) ; // in which 65535 = (2^16 - 1) it results in 149. 5689 which is the resistance value of the resistor that I connected.

    But still I am not able to read the right value and I believe it is coding issue. Before I get to this issue I would like to make sure one thing. When I send START command it does not have any impact as you can see below since ADS114S08 is still in conversion mode according to the DRDY pin. I understood that but why DRDY (channel 4) goes HIGH when I send my first dummy value.


    Bob, regarding the issues related to the TIVA that would be great if we can invite someone who can help us on TIVA. Thanks...

  • Hi Fatih,

    There are a number of things to consider.  First thing is the data will be transmitted directly out of the device when SPI clocks are issued.  Notice that the data is repeated and the same result is shown either by reading the result directly or by RDATA command.

    Second, DRDY will always go high once SCLKs begin to be issued (if it is in a low state otherwise remains high until completion of the next conversion).  Note Figure 86 in the ADS114S08 datasheet.  DRDY will stay high until the end of conversion when it transitions from high to low state.  If in single-shot mode, DRDY will remain high until a START command is issued and will not go low until the conversion has completed and the result is ready to be read out from the device.

    As far as the START command, what impact are you expecting to see?  The START command has no effect in the continuous conversion mode except for the first start issued from the idle state which starts the device converting.  A new conversion will start if the START command is issued in single-shot conversion mode if in the idle state.  DRDY will not go low and back high as that would mean a valid conversion has completed and results are ready.

    As the measurement is ratiometric, you can make the calculation as you have shown as the output code will be a ratio of the RTD resistance to the reference resistor value.  The result is the same with respect to using the voltage measurement except you have additional math to convert the voltage back to resistance.  With 1mA of excitation current the reference voltage is 1V (with a 1k Ohm reference resistor).  I would expect to see 150mV across the RTD resistor if it is 150 Ohm.  Using the same formula you have shown for determining resistance, you replace the resistance value with a voltage value.

    RTD_Voltage = ( 2 * VREF * result / PGA ) / (65535) ; // in which 65535 = (2^16 - 1) it results in 149.5689 mV

    To get the resistance value you divide the voltage by the current (149,5689mV / 1mA = 149.5689 Ohm).

    As the temperature is calculated from the resistance, the initial ratiometric formula you have given reduces any calculation error with floating point math as it is unnecessary to calculate to voltage then to resistance.

    Now the last thing is confusing to me where you state at the beginning that you are now able to read the correct value, but in the next sentence you think you have a coding issue as you are not able to read the correct value.  Does this mean you see the correct value on the Saleae, but not in your code?

    Best regards,

    Bob B

  • Hi Fatih,

    The Tiva code is pretty well documented as to the functionality. Use the ssi.c file and review the various functions. To begin reading the data, issue the SSIDataGetNonBlocking() function within a while() to empty the FIFO first before sending any data.

    If you PUT 4 bytes of data you need to GET 4 bytes of data. For the read data command sequence you have shown, you need to throw away the first 2 bytes, then capture the next two bytes as your result. You need to assemble your data correctly by GETting the MSB and saving it to another variable by left shifting the data by 8. Then GET the LSB and save that by adding the value of the LSB to the MSB variable. That should be your result.

    Best regards,
    Bob B
  • Hi Bob,

    Now, I am able to read the result.

    As you stated the following "DRDY will remain high until a START command is issued and will not go low until the conversion has completed and the result is ready to be read out from the device." I was expecting the START command to start the conversion by taking the DRDY to HIGH not on the first SCLK rising edge.

    From Figure 82 in datasheet, after the first conversion is completed the device goes to standby mode if it is in single-shot conversion mode. At standby mode I was expecting DRDY is to be LOW since the first conversion is completed already and indicating that data is ready. New data conversion is initiated with START command. Once the START command is issued DRDY will go HIGH and will no go low until the new conversion has completed as you stated earlier as well.  However, I can not observe this behavior in my results. It looks like I always send the START command while DRDY is HIGH, which means conversion has not been completed. According to the section 9.5.3.5 in datasheet, the START command has no effect if the device is already in conversion mode, My observation is that I always send the START command during conversion.

      

  • "Now the last thing is confusing to me where you state at the beginning that you are now able to read the correct value, but in the next sentence you think you have a coding issue as you are not able to read the correct value. Does this mean you see the correct value on the Saleae, but not in your code?"

    Yes, I was seeing the correct value on Saleae , but not in your code. But as I said earlier, now I can see the correct value in both.
  • Hi Fatih,

    You are correct regarding the usage of the START command. The START command will have no effect if the conversion is already in progress. I updated my earlier response for clarity as some of our devices will restart the conversion, however this device does not as you have corrected me.

    As to the DRDY in the Saleae shots you have shown, the DRDY is low at the start which means a conversion has completed but not yet read from the device. Unfortunately the ADS114S08 is not smart enough to know the intentions of the user but rather will assume that the DRDY is being acknowledged and thus the reason for the communication is to read the result from the device sending DRDY back high. You will then know that the START command has been properly executed when DRDY falls once again at the prescribed data rate.

    Best regards,
    Bob B
  • Hi Bob,

    So you are telling me that the results on saleae are fine. I just wanted to make sure that my start command is not ignored just because I am sending it when the device is still in conversion. Please correct me if I am wrong but the result below shows me that START command actually is not ignored and conversion starts again once the previous one is completed.

  • Actually, I will later use potentiometer and change it to see if the START command is really working fine. I am little bit suspicious about that since I may keep reading the same value after the first conversion if START command had not worked. To me, the only way is to change the resistor value and observe the results..
  • Hi Fatih,

    You are confusing DRDY going high with start of conversion. In single-shot mode the conversion only starts with the START command or by raising the START pin. If you don't send the START command, then DRDY will go high when the previous conversion result is read and it will stay high until the START command is issued and the conversion completes. If the START command wasn't working, then you would not see DRDY go low. But because it does go low, the START command is working.

    Best regards,
    Bob B
  • Hi Bob,

    I just wanted to make sure that the START command is working properly.

    Thanks a lot for you help. Our discussions were really informative.