TMS320F28379D: ADS1258: AIN0 data not read using TMS320 controller.

Part Number: TMS320F28379D
Other Parts Discussed in Thread: ADS1258,

Tool/software:

I used the ADS1258 EVM software to verify the ADC output values for known input voltages and prepared an Excel table as shown below. Could you please check if the formulae I used are correct?

Now, instead of the PGA/EVM board, I have interfaced the ADS1258 with a TMS320F28379D controller. When I apply 0 V at AIN0, the oscilloscope shows that the hex code read is 0x9595EFCECF. Considering only the last 3 bytes (0xEFCECF), the calculated voltage is 0.316  and expected should be close to −2.24 V, but I am not getting the expected result. I have also attached my code. Can you please review and tell me what exactly might be wrong?

Input Voltage Hex (24-bit) Unsigned (dec) Signed (dec) Formula used VINV_{IN} (V) Actual AIN0 (V)
3.3 V 0x26054B 2,491,723 +2,491,723 IN = (Code / 2^23) × VREF 0.7426 0.7426 + VREF
0 V (GND) 0x8CFABD 9,239,229 9,239,229 − 16,777,216 = −7,537,987 If u ≥ 2^23 → s = u − 2^24, then IN = (s / 2^23) × VREF −2.2465 −2.2465 + VREF

 "F28x_Project.h"
#include "ADS1258.h"

/* Initialize arrays */
uint8_t DataTx[5] = { 0 };
uint8_t DataRx[5] = { 0 };
uint8_t regVal ;
uint8_t data[];
uint8_t dataRx,dataPosition,byteLength;
int count;
int  EPWM1_TIMER_TBPRD,EPWM1_MAX_CMPA,EPWM1_MIN_CMPA,EPWM1_CMP_UP,EPWM1_CMP_DOWN;    // Period register
static uint8_t registerMap[NUM_REGISTERS];
int i;
int32_t dataValues[5];
uint8_t writeValues[7], statusBytes[5];
int32_t upperByte,middleByte,lowerByte;
void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.

    InitSysCtrl();


// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// Setup only the GPIO only for SPI-A functionality
// This function is found in F2837xD_Spi.c
   InitSpiaGpio();
   InitADS1258Gpio();

   // Enable PWM1, PWM6
   CpuSysRegs.PCLKCR2.bit.EPWM1=1;

   // For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
   // These functions are in the F2837xD_EPwm.c file
   InitEPwm1Gpio();

// Step 3. Clear all interrupts:
   DINT;

//
// Initialize PIE control registers to their default state.
// The default state is all PIE __interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU __interrupts and clear all CPU __interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the __interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
   InitPieVectTable();


    // Enable global Interrupts and higher priority real-time debug events:
    IER = M_INT1 |M_INT3 | M_INT8 ;                        // For ADCA0,EPWM1 and for SCIC_RX


    EPWM1_TIMER_TBPRD=2;  // Period register
    EPWM1_MAX_CMPA=1;
    EPWM1_MIN_CMPA=1;

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;
    InitEPwm1Example();
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;

    //worktime start
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

// Step 4. Initialize the Device Peripherals:
   spi_fifo_init();     // Initialize the SPI FIFO

// Step 5. User specific code:
   adcStartupRoutine();

   for(;;)
   {
     readSingleRegister(0x02);
     DELAY_US(10000);
     DELAY_US(10000);
     DELAY_US(10000);

       // Wait and check that /DRDY interrupt occurred
       // b_pass &= waitForDRDYinterrupt(10);
       //  Read data in read direct mode
       dataValues[i] = readData(&statusBytes[i], NULL, DIRECT);

       DELAY_US(10000);
   }
}

void adcStartupRoutine(void)
{
    /* (OPTIONAL) Provide additional delay time for power supply settling */
    DELAY_US(50000);

    /* (REQUIRED) Set nRESET/nPWDN pin high for ADC operation */
    GpioDataRegs.GPBCLEAR.bit.GPIO52 = 1;  // PWDN low
    DELAY_US(100);
    GpioDataRegs.GPBSET.bit.GPIO52 = 1;    // PWDN high
    DELAY_US(10000);

    /* (REQUIRED) tWAKE delay */
    DELAY_US(5000);

    /* (OPTIONAL) Toggle nRESET pin to assure default register settings. */
    /* NOTE: This also ensures that the device registers are unlocked.   */
    GpioDataRegs.GPDCLEAR.bit.GPIO97 = 1;  // RESET low
    DELAY_US(1000);
    GpioDataRegs.GPDSET.bit.GPIO97 = 1;    // RESET high
    DELAY_US(3000);

    GpioDataRegs.GPCSET.bit.GPIO67 = 1;    // START high
}


uint8_t spiSendReceiveByte(uint8_t dataTx)
{
    // Wait until the transmit buffer is empty
    while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);

    // Write data to the transmit buffer
    SpiaRegs.SPITXBUF =dataTx << 8;  // Upper byte used

    dataRx = SpiaRegs.SPIRXBUF << 8;
}

uint8_t spiSendReceiveByte1(uint8_t dataTx)
{
    // Wait until the transmit buffer is empty
    while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);

    // Write data to the transmit buffer
    SpiaRegs.SPITXBUF =dataTx << 8;  // Upper byte used

    dataRx = SpiaRegs.SPIRXBUF << 8;

    return dataRx;
}

void spiSendReceiveArrays(uint8_t DataTx[], uint8_t DataRx[], uint8_t byteLength)
{
    /* Set the nCS pin LOW */
    GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1;   // CS LOW

    spiSendReceiveByte(DataTx[0]);
    spiSendReceiveByte(DataTx[1]);

    DELAY_US(10);
    GpioDataRegs.GPBSET.bit.GPIO61 = 1; // CS HIGH
}

void spiSendReceiveArrays1(uint8_t DataTx[], uint8_t DataRx[], uint8_t byteLength)
{
    /* Set the nCS pin LOW */
    GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1; //CS LOW

    for (i = 0; i < 5; i++)
    {
        DataRx[i] = spiSendReceiveByte1(DataTx[i]);
    }

    DELAY_US(1000);
    GpioDataRegs.GPBSET.bit.GPIO61 = 1;  //CS HIGH
}

void spi_fifo_init()
{
    //
    // Initialize SPI FIFO registers
    //
    SpiaRegs.SPIFFTX.all = 0xE040;
    SpiaRegs.SPIFFRX.all = 0x2044;
    SpiaRegs.SPIFFCT.all = 0x0;

    //
    // Initialize core SPI registers
    //
    InitSpi();
}

void InitADS1258Gpio(void)
{
    EALLOW;

    GpioCtrlRegs.GPBMUX2.bit.GPIO52 = 0;  // GPIO80 as GPIO
    GpioCtrlRegs.GPBDIR.bit.GPIO52 = 1;   // Output (PWDN)

    GpioCtrlRegs.GPDMUX1.bit.GPIO97 = 0;  // GPIO84 as GPIO
    GpioCtrlRegs.GPDDIR.bit.GPIO97 = 1;   // Output (RESET)

    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 0;   // GPIO4 as GPIO
    GpioCtrlRegs.GPCDIR.bit.GPIO67 = 1;    // Output (START)

    GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 0;   // GPIO4 as GPIO
    GpioCtrlRegs.GPBDIR.bit.GPIO61 = 1;    // Output (CS)

    GPIO_SetupPinMux(22, GPIO_MUX_CPU1, 0);   // GPIO22 as GPIO
    GPIO_SetupPinOptions(22, GPIO_INPUT, 0);  // Input, no pullup/down

    EDIS;

}

uint8_t readSingleRegister(uint8_t address)
{
    /* Build TX array and send it */
    DataTx[0] = OPCODE_RREG | (address & OPCODE_A_MASK);
    spiSendReceiveArrays(DataTx, DataRx, 2);
}


void InitEPwm1Example()
{
   //
   // Setup TBCLK
   //
   EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
   EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;       // Set timer period
   EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
   EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
   EPwm1Regs.TBCTR = 0x0000;                  // Clear counter
   EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;   // Clock ratio to SYSCLKOUT
   EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

   //
   // Setup shadow register load on ZERO
   //
   EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
   EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
   EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
   EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

   //
   // Set Compare values
   //
   EPwm1Regs.CMPA.bit.CMPA = EPWM1_MIN_CMPA;     // Set compare A value

   //
   // Set actions
   //
   EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
   EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A,

   //
   // Interrupt where we will change the Compare Values
   //
   EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
   EPwm1Regs.ETSEL.bit.INTEN = 1;                // Enable INT
   EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;           // Generate INT on 3rd event

}

int32_t readData(uint8_t status[], uint8_t data[], readMode mode)
{

        DataTx[0] = OPCODE_READ_COMMAND | OPCODE_MUL_MASK;
       dataPosition = 2;
       byteLength=5;
         spiSendReceiveArrays1(DataTx, DataRx, byteLength);

        data[0] = DataRx[dataPosition + 0];
        data[1] = DataRx[dataPosition + 1];
        data[2] = DataRx[dataPosition + 2];

    int32_t signByte;
    if (DataRx[dataPosition] & 0x80u) { signByte = 0xFF000000; }
    else                              { signByte = 0x00000000; }

     upperByte   = ((int32_t) DataRx[dataPosition + 0] & 0xFF) << 16;
    middleByte  = ((int32_t) DataRx[dataPosition + 1] & 0xFF) << 8;
    lowerByte   = ((int32_t) DataRx[dataPosition + 2] & 0xFF) << 0;

    return (signByte | upperByte | middleByte | lowerByte);
}

uint8_t getRegisterValue(uint8_t address)
{
    assert(address < NUM_REGISTERS);
    return registerMap[address];
}
void InitSpi(void)
{
    // Initialize SPI-A

    // Set reset low before configuration changes
    // Clock polarity (0 == rising, 1 == falling)
    // 16-bit character
    // Enable loop-back
    SpiaRegs.SPICCR.bit.SPISWRESET = 0;

    SpiaRegs.SPIPRI.bit.TRIWIRE = 0;
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;
    SpiaRegs.SPICCR.bit.SPICHAR = 7;
    SpiaRegs.SPICCR.bit.SPILBK = 0;

    // Enable master (0 == slave, 1 == master)
    // Enable transmission (Talk)
    // Clock phase (0 == normal, 1 == delayed)
    // SPI interrupts are disabled
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;
    SpiaRegs.SPICTL.bit.TALK = 1;
    SpiaRegs.SPICTL.bit.CLK_PHASE = 1;
    SpiaRegs.SPICTL.bit.SPIINTENA = 0;

    // Set the baud rate
    SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = 24;

    // Set FREE bit
    // Halting on a breakpoint will not halt the SPI
    SpiaRegs.SPIPRI.bit.FREE = 1;

    // Release the SPI from reset
    SpiaRegs.SPICCR.bit.SPISWRESET = 1;
}

void InitSpiGpio()
{
   InitSpiaGpio();
}

//
// InitSpiaGpio - Initialize SPIA GPIOs
//
void InitSpiaGpio()
{
   EALLOW;

    //
    // Enable internal pull-up for the selected pins
    //
    // Pull-ups can be enabled or disabled by the user.
    // This will enable the pullups for the specified pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPBPUD.bit.GPIO58 = 0;  // Enable pull-up on GPIO16 (SPISIMOA)
    GpioCtrlRegs.GPBPUD.bit.GPIO59 = 0;  // Enable pull-up on GPIO17 (SPISOMIA)
    GpioCtrlRegs.GPBPUD.bit.GPIO60 = 0;  // Enable pull-up on GPIO18 (SPICLKA)
 //   GpioCtrlRegs.GPBPUD.bit.GPIO61 = 0;  // Enable pull-up on GPIO19 (SPISTEA)

    //
    // Set qualification for selected pins to asynch only
    //
    // This will select asynch (no qualification) for the selected pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPBQSEL2.bit.GPIO58 = 3; // Asynch input GPIO16 (SPISIMOA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO59 = 3; // Asynch input GPIO17 (SPISOMIA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO60 = 3; // Asynch input GPIO18 (SPICLKA)
  //  GpioCtrlRegs.GPBQSEL2.bit.GPIO61 = 3; // Asynch input GPIO19 (SPISTEA)


    GpioCtrlRegs.GPBGMUX2.bit.GPIO58 = 3; // Configure GPIO16 as SPISIMOA
    GpioCtrlRegs.GPBGMUX2.bit.GPIO59 = 3; // Configure GPIO17 as SPISOMIA
    GpioCtrlRegs.GPBGMUX2.bit.GPIO60 = 3; // Configure GPIO18 as SPICLKA
 //   GpioCtrlRegs.GPBGMUX2.bit.GPIO61 = 3; // Configure GPIO19 as SPISTEA
    //
    //Configure SPI-A pins using GPIO regs
    //
    // This specifies which of the possible GPIO pins will be SPI functional
    // pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 3; // Configure GPIO16 as SPISIMOA
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 3; // Configure GPIO17 as SPISOMIA
    GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 3; // Configure GPIO18 as SPICLKA
 //   GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 3; // Configure GPIO19 as SPISTEA

    EDIS;
}