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.

TM4C and ADS1256

Other Parts Discussed in Thread: ADS1256, ADS1146

Hi

I'm trying to communicate with a ADS1256 from my TM4C123.

I try to write the DRATE register and I want to read it back in order to make sure the command works.

Unfortunately I always get back 4 bytes and the value changes each time.

Has someone already tried to use this chip?

SPI works on other sensors:

SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
SSIEnable(SSI0_BASE);

Here my init code

Optimization is off.

int i;

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0);//CS up
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, 0);//CS down

//Empty Input buffer
uint32_t data[2];
while(SSIDataGetNonBlocking(SSI0_BASE, &data[0])){}

//reset ADS1256
SSIDataPut(SSI0_BASE, 0b11111110);
while(SSIBusy(SSI0_BASE))
{
}
for(i=0; i<1000;i++);

//SDATAC Stop continous reading
SSIDataPut(SSI0_BASE, 0b00001111);
while(SSIBusy(SSI0_BASE))
{
}
for(i=0; i<1000;i++);


//WREG DRATE
SSIDataPut(SSI0_BASE, 0x53);
while(SSIBusy(SSI0_BASE))
{
}
SSIDataPut(SSI0_BASE, 0x00);
while(SSIBusy(SSI0_BASE))
{
}
SSIDataPut(SSI0_BASE, 0xC0);
while(SSIBusy(SSI0_BASE))
{
}
for(i=0; i<1000;i++);

//WREG MUX
SSIDataPut(SSI0_BASE, 0x51);
while(SSIBusy(SSI0_BASE))
{
}
SSIDataPut(SSI0_BASE, 0x00);
while(SSIBusy(SSI0_BASE))
{
}
SSIDataPut(SSI0_BASE, 0x01);
while(SSIBusy(SSI0_BASE))
{
}
for(i=0; i<1000;i++);


//RREG DRATE
SSIDataPut(SSI0_BASE, 0x13);
while(SSIBusy(SSI0_BASE))
{
}
SSIDataPut(SSI0_BASE, 0x00);
while(SSIBusy(SSI0_BASE))
{
}
//wait 12.5us min 6us
for(i=0; i<1000;i++);


SSIDataGet(SSI0_BASE, &data[0]);

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0);//CSLens up

  • Hello Daniel,

    The first thing is that during a SSIDataPut for the Transmit, ensure that the SSIDataGet is called to flush out the data, so that when RX operation is being done, the SSIDataGet returns the FIFO data with the actual RX from the Slave. Also the flushing operation must be performed before a transaction: Makes it cleaner.

    Regards
    Amit
  • Thanks for your help.
    Unfortunately it did not work yet. I still get random numbers and nowhere a the 192(0xC0) I'd like to write to DREG
    I did not get your comment about flushing before transaction


    Here my updated code

    int i;

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0);//CSLens up
    for(i=0;i<1000;i++);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, 0);//CSLens down

    //Empty Input buffer
    uint32_t data[2];
    while(SSIDataGetNonBlocking(SSI0_BASE, &data[0])){}
    for(i=0; i<200;i++);


    //WREG DRATE
    SSIDataPut(SSI0_BASE, 0x53);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);

    SSIDataPut(SSI0_BASE, 0x00);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);

    SSIDataPut(SSI0_BASE, 0xC0);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);

    //WREG MUX
    SSIDataPut(SSI0_BASE, 0x51);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);

    SSIDataPut(SSI0_BASE, 0x00);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);

    SSIDataPut(SSI0_BASE, 0x01);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<200;i++);


    //RREG DRATE
    SSIDataPut(SSI0_BASE, 0x13);
    while(SSIBusy(SSI0_BASE))
    {
    }
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);


    SSIDataPut(SSI0_BASE, 0x00);
    while(SSIBusy(SSI0_BASE))
    {
    }
    //wait 12.5us min 6us
    SSIDataGet(SSI0_BASE, &data[0]);
    for(i=0; i<100;i++);

    SSIDataPut(SSI0_BASE, 0x00);
    while(SSIBusy(SSI0_BASE))
    {
    }
    //wait 12.5us min 6us
    SSIDataGet(SSI0_BASE, &data[1]);
    for(i=0; i<100;i++);

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0);//CSLens up
  • Hello Daniel,

    Can you please share the SSI configuration code and the GPIO configuration code. As from the post I see that you have PA0 connected from the TM4C device as CS for the ADS. Is that correct?

    Regards
    Amit
  • Yes that is correct we have 4 SPI devices on our chip
    Here also the smaller code for SPI:

    int i;
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0);//CSLens up
    for(i=0;i<1000;i++);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, 0);//CSLens down

    //WREG DRAT
    SSIDataPut(SSI0_BASE, 0x53);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);
    SSIDataPut(SSI0_BASE, 0x00);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);
    SSIDataPut(SSI0_BASE, 0xC0);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);

    //WREG MUX
    SSIDataPut(SSI0_BASE, 0x51);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);
    SSIDataPut(SSI0_BASE, 0x00);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);
    SSIDataPut(SSI0_BASE, 0x01);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);


    //Empty Input buffer
    uint32_t data[3];
    while(SSIDataGetNonBlocking(SSI0_BASE, &data[0]));
    for(i=0; i<200;i++);


    //RREG DRATE
    SSIDataPut(SSI0_BASE, 0x13);while(SSIBusy(SSI0_BASE));
    for(i=0; i<100;i++);
    SSIDataPut(SSI0_BASE, 0x00);while(SSIBusy(SSI0_BASE));
    for(i=0; i<200;i++);

    SSIDataGet(SSI0_BASE, &data[0]);
    SSIDataGet(SSI0_BASE, &data[1]);
    SSIDataPut(SSI0_BASE, 0xFF);while(SSIBusy(SSI0_BASE));
    SSIDataGet(SSI0_BASE, &data[2]);
    for(i=0; i<100;i++);

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0);//CSLens up


    Here the code for SPI configuration:


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    /* SPI0 */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);


    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    //GPIOPinConfigure(GPIO_PA3_SSI0FSS); //CS done by hand
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);

    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);//Set CS for chip one
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);//CS up

    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_6); //Set CS for chip two
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_PIN_6); //CSLED up

    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_1); //set CS for ADS1146
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_1, GPIO_PIN_1); //CSADS up

    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_0); //set CS for ADS1256
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_PIN_0); //CSADS up

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5); // Do not include CS pin 3 (FSS)

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 500000, 8);
    SSIEnable(SSI0_BASE);

    B134_332_initDMA();
    SPI_init();
  • Hello Daniel,

    As I read from the ADS data sheet, there are two pieces of information I could see

    1. The Frame Format must be SSI_FRF_MOTO_MODE_1 instead of SSI_FRF_MOTO_MODE_0 as the sampling edge for the ADS is falling while launch edge is rising
    2. Secondly between the operations, the CS must be deasserted.

    Regards
    Amit
  • Amit Ashara said:
    2. Secondly between the operations, the CS must be deasserted.



    Yes it's true the CS works in inverted logic, hence the bar over it in the datasheet.

    If you only want 1 slave you can simply use a pull-down. In the table "TIMING CHARACTERISTICS FOR FIGURE 1"  it says that on note 3

  • Dear Amit,

    Thanks a lot that helped. The chip is now up and running.

    1.) We are also using ADS1146 where we need to work with SSI_FRF_MOTO_MODE_0.

    Do you know the correct way to change this mode between each readout on the fly?

    2.) The deasserting of the CS was necessary even though it states that this pin can be set to GND.

  • Hello Daniel,

    Yes, it can be done. However before changing the mode please do use SSIDisable to disable the SSI controller

    Regards
    Amit
  • While it's true that it, "Can be done" - it's useful often to ask, "Is it wise to do?"  Our experience - most often - NO!

    ARM MCUs are famed for having multiple instantiations of peripherals - using a 2nd SPI port would enable your far simpler, "Set-up once & forget!"

    Too often we've seen clients employ this "kitchen sink" (i.e. time division multiplex) of a peripheral - and undergo intense "pain/suffering" for their efforts.  (should either of your SPI slaves "demand" quick service - and they're "off-line" (due to the other being currently selected) time muxing fails, most always...)

    KISS argues for one peripheral "attaching" to one accessory - at least until the application becomes well known - and time bounded...