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.

TIDA-010087: SPI Receive ISR Not Triggering for First ADS131M08 Device – Based on TIDA-010087 Reference Design

Part Number: TIDA-010087
Other Parts Discussed in Thread: ADS131M08, TMS320F28388S

Tool/software:

Dear TI E2E Team,

I am currently working on a project where I am referring to the TIDA-010087 software design. However, my hardware differs slightly: instead of a single ADS131M08 device as used in TIDA-010087, my project requires two ADS131M08 chips to handle 12 AC signals.

In my hardware design, I have connected both ADS131M08 devices to the SPIB port of the TMS320F28388S microcontroller, using separate chip select (CS) lines for each ADC.

My configuration is as follows:

  • ADC1:

    • DRDY → routed to ISR4

    • SPIB_RX → mapped to ISR7

  • ADC2:

    • DRDY → routed to ISR5

    • SPIB_RX → mapped to ISR8

Currently, both ISR4 and ISR5 are triggering as expected when the DRDY signals go low.

However, only ISR8 (for ADC2’s SPIB_RX) is getting triggered. ISR7 (for ADC1’s SPIB_RX) is not triggering at all.

Could you please provide your expert guidance on what might be causing this issue and how to resolve it?

I have attached my software source file for your reference.

Looking forward to your valuable input.

// Global variables for the ADCs
ads131m0x_data AC3PH_ExtAdc1;
ads131m0x_data AC3PH_ExtAdc2;
volatile uint16_t AC3PH_ExtAdcRxflag1 = 0;
volatile uint16_t AC3PH_ExtAdcRxflag2 = 0;
volatile int32_t ads131m08_adc1_latestSamples[8];
volatile int32_t ads131m08_adc2_latestSamples[8];

void AC3PH_HAL_GpioWrite(uint32_t GPIO_NUM, uint16_t state)
{
    GPIO_writePin(GPIO_NUM, state & 0x01);
}

void AC3PH_HAL_setupExtAdcInterrupt(void)
{
    // Register interrupt handlers for ADC1
    Interrupt_register(AC3PH_EXT_ADC1_INT_DRDY, &AC3PH_EXT_ADC1_ISR_DRDY);
    Interrupt_register(AC3PH_EXT_ADC_INT_SPI_RX, &AC3PH_EXT_ADC1_ISR_SPI_RXFIFO);
    
    // Register interrupt handlers for ADC2
    Interrupt_register(AC3PH_EXT_ADC2_INT_DRDY, &AC3PH_EXT_ADC2_ISR_DRDY);
    Interrupt_register(AC3PH_EXT_ADC_INT_SPI_RX, &AC3PH_EXT_ADC2_ISR_SPI_RXFIFO);
}

void AC3PH_HAL_enableExtAdcInterrupt(void)
{
    // Enable interrupts for ADC1
    Interrupt_enable(AC3PH_EXT_ADC1_INT_DRDY);
    
    // Enable interrupts for ADC2
    Interrupt_enable(AC3PH_EXT_ADC2_INT_DRDY);

    // Clear and reset SPI FIFOs
    SPI_resetRxFIFO(AC3PH_EXT_ADC_SPI_BASE);
    SPI_resetTxFIFO(AC3PH_EXT_ADC_SPI_BASE);
    SPI_clearInterruptStatus(AC3PH_EXT_ADC_SPI_BASE, SPI_INT_RXFF);
    
    // Enable SPI RX interrupt
    Interrupt_enable(AC3PH_EXT_ADC_INT_SPI_RX);
}

void AC3PH_HAL_enableGlobalInterrupt(void)
{
    EALLOW;
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global real-time interrupt DBGM
    EDIS;
}

// ISR for ADC1 DRDY
#pragma CODE_SECTION(ISR4,"isrcodefuncs");
#pragma INTERRUPT(ISR4, HPI)
interrupt void ISR4(void)
{
    //
    // ISR is triggered by DRDY1
    //
    AC3PH_HAL_ExtAdc1SendTxFrame();
    AC3PH_HAL_GpioWrite(AC3PH_TEST_GPIO, 1);
    //AC3PH_runPwmIsr();
    AC3PH_HAL_GpioWrite(AC3PH_TEST_GPIO, 0);
    AC3PH_HAL_DrdyGpio1AckInterrupt();
}

// ISR for ADC2 DRDY
#pragma CODE_SECTION(ISR5,"isrcodefuncs");
#pragma INTERRUPT(ISR5, HPI)
interrupt void ISR5(void)
{
    //
    // ISR is triggered by DRDY2
    //
    AC3PH_HAL_ExtAdc2SendTxFrame();
    AC3PH_HAL_GpioWrite(AC3PH_TEST_GPIO, 1);
    //AC3PH_runPwmIsr();
    AC3PH_HAL_GpioWrite(AC3PH_TEST_GPIO, 0);
    AC3PH_HAL_DrdyGpio2AckInterrupt();
}

// ISR for ADC1 SPI RX
#pragma CODE_SECTION(ISR7,"isrcodefuncs");
#pragma INTERRUPT(ISR7, HPI)
interrupt void ISR7(void)
{
    //
    // ISR is triggered by the SPIB_RX for ADC1
    //
    AC3PH_HAL_ExtAdc1Read(); // This function reads the expected number of words
    AC3PH_HAL_SpiRxFifoAckInterrupt();
}

// ISR for ADC2 SPI RX
#pragma CODE_SECTION(ISR8,"isrcodefuncs");
#pragma INTERRUPT(ISR8, HPI)
interrupt void ISR8(void)
{
    //
    // ISR is triggered by the SPIB_RX for ADC2
    //
    AC3PH_HAL_ExtAdc2Read(); // This function reads the expected number of words
    AC3PH_HAL_SpiRxFifoAckInterrupt();
}

void AC3PH_HAL_setupGpioExtAdcClk(void)
{
    SysCtl_setAuxClock(
                    SYSCTL_AUXPLL_OSCSRC_XTAL     |            // 20 MHz crystal in
                    SYSCTL_AUXPLL_IMULT(25)       |            // integer ×25
                    SYSCTL_REFDIV(2U)             |
                    SYSCTL_ODIV(4U)               |
                    SYSCTL_AUXPLL_DIV_1           |            // divide VCO → 64 MHz
                    SYSCTL_AUXPLL_ENABLE          |            // turn AUXPLL on
                    SYSCTL_DCC_BASE_0
                );

    SysCtl_selectClockOutSource(SYSCTL_CLOCKOUT_AUXPLLCLK);

    //
    // Configure the XCLOUT clock divider. The divider can be /1, /2, /4 or /8.
    //
    SysCtl_setXClk(SYSCTL_XCLKOUT_DIV_8);

    //
    // Configure GPIO73 as XCLKOUT pin.
    //
    GPIO_setPinConfig(GPIO_73_XCLKOUT);
}

void AC3PH_HAL_SetupSpiGpio(void){

    //
    // Configure SPI GPIO pins for SPIB
    //
    GPIO_setQualificationMode(AC3PH_EXT_ADC1_SDIN_GPIO_NUM, GPIO_QUAL_ASYNC);
    GPIO_setQualificationMode(AC3PH_EXT_ADC1_SDOUT_GPIO_NUM, GPIO_QUAL_ASYNC);
    GPIO_setQualificationMode(AC3PH_EXT_ADC1_SCLK_GPIO_NUM, GPIO_QUAL_ASYNC);
    GPIO_setPinConfig(AC3PH_EXT_ADC1_SDIN_PIN_CONFIG);
    GPIO_setPinConfig(AC3PH_EXT_ADC1_SDOUT_PIN_CONFIG);
    GPIO_setPinConfig(AC3PH_EXT_ADC1_SCLK_PIN_CONFIG);

    //
    // Configure CSn pin for ADC1
    //
    GPIO_setPadConfig(AC3PH_EXT_ADC1_CS_GPIO_NUM, GPIO_PIN_TYPE_PULLUP);
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 1);
    GPIO_setPinConfig(AC3PH_EXT_ADC1_CS_PIN_CONFIG_GPIO);
    GPIO_setDirectionMode(AC3PH_EXT_ADC1_CS_GPIO_NUM, GPIO_DIR_MODE_OUT);
    
    //
    // Configure CSn pin for ADC2
    //
    GPIO_setPadConfig(AC3PH_EXT_ADC2_CS_GPIO_NUM, GPIO_PIN_TYPE_PULLUP);
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 1);
    GPIO_setPinConfig(AC3PH_EXT_ADC2_CS_PIN_CONFIG_GPIO);
    GPIO_setDirectionMode(AC3PH_EXT_ADC2_CS_GPIO_NUM, GPIO_DIR_MODE_OUT);
}

void AC3PH_HAL_SetupSpi(void)
{
    //
    // Must put SPI into reset before configuring it
    //
    SPI_disableModule(AC3PH_EXT_ADC_SPI_BASE);
    //
    // SPI configuration. Use a 1MHz SPICLK and 16-bit word size.
    //
    SPI_enableHighSpeedMode(AC3PH_EXT_ADC_SPI_BASE);
    SPI_setConfig(AC3PH_EXT_ADC_SPI_BASE,
                  SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ),
                  SPI_PROT_POL0PHA0,
                  SPI_MODE_CONTROLLER, AC3PH_EXT_ADC_SPI_CLOCK_FREQ_HZ, 16);


    SPI_setEmulationMode(AC3PH_EXT_ADC_SPI_BASE, SPI_EMULATION_STOP_MIDWAY);
    SPI_enableFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_clearInterruptStatus(AC3PH_EXT_ADC_SPI_BASE,
                             SPI_INT_RX_DATA_TX_EMPTY
                             |SPI_INT_RXFF|SPI_INT_TXFF );

    SPI_setFIFOInterruptLevel(AC3PH_EXT_ADC_SPI_BASE,
                              SPI_FIFO_TX0, SPI_FIFO_RX10);

    SPI_enableInterrupt(AC3PH_EXT_ADC_SPI_BASE, SPI_INT_RXFF|SPI_INT_TXFF);

    //
    // Configuration complete. Enable the module.
    //
    SPI_enableModule(AC3PH_EXT_ADC_SPI_BASE);
}

void AC3PH_HAL_setupGpioExtAdc(void)
{
    // Configure HWINT GPIO for External Adc1 DRDY pin
    GPIO_setPinConfig(AC3PH_EXT_ADC1_DRDY_PIN_CONFIG_GPIO);
    GPIO_setDirectionMode(AC3PH_EXT_ADC1_DRDY_GPIO_NUM, GPIO_DIR_MODE_IN);
    GPIO_setQualificationMode(AC3PH_EXT_ADC1_DRDY_GPIO_NUM, GPIO_QUAL_SYNC);

    GPIO_setInterruptPin(AC3PH_EXT_ADC1_DRDY_GPIO_NUM, GPIO_INT_XINT1);

    // Configure XINT1 to be triggered by a falling edge
    GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_FALLING_EDGE);

    // Enable XINT1
    GPIO_enableInterrupt(GPIO_INT_XINT1);
    
    // Configure HWINT GPIO for External Adc2 DRDY pin
    GPIO_setPinConfig(AC3PH_EXT_ADC2_DRDY_PIN_CONFIG_GPIO);
    GPIO_setDirectionMode(AC3PH_EXT_ADC2_DRDY_GPIO_NUM, GPIO_DIR_MODE_IN);
    GPIO_setQualificationMode(AC3PH_EXT_ADC2_DRDY_GPIO_NUM, GPIO_QUAL_SYNC);

    GPIO_setInterruptPin(AC3PH_EXT_ADC2_DRDY_GPIO_NUM, GPIO_INT_XINT2);

    // Configure XINT2 to be triggered by a falling edge
    GPIO_setInterruptType(GPIO_INT_XINT2, GPIO_INT_TYPE_FALLING_EDGE);

    // Enable XINT2
    GPIO_enableInterrupt(GPIO_INT_XINT2);

    // Configure Reset pin for the External ADC1
    GPIO_setPadConfig(AC3PH_EXT_ADC1_RST_GPIO_NUM, GPIO_PIN_TYPE_PULLUP);
    GPIO_writePin(AC3PH_EXT_ADC1_RST_GPIO_NUM, 1);
    GPIO_setPinConfig(AC3PH_EXT_ADC1_RST_PIN_CONFIG_GPIO);
    GPIO_setDirectionMode(AC3PH_EXT_ADC1_RST_GPIO_NUM, GPIO_DIR_MODE_OUT);
    
    // If using separate reset pin for ADC2, configure it here
    // Otherwise, we're sharing the reset pin with ADC1
}

void AC3PH_HAL_setupExtAdc(void)
{
    //
    //(OPTIONAL) Provide additional delay time for power supply settling
    //
    delay_ms(50);

    //
    //(REQUIRED) Set nRESET pin high for ADC operation
    //
    GPIO_writePin(AC3PH_EXT_ADC1_RST_GPIO_NUM, 1);
    delay_ms(1);

    // Setup ADC1
    //
    //(REQUIRED) Configure MODE register settings for ADC1
    //
    while(!GPIO_readPin(AC3PH_EXT_ADC1_DRDY_GPIO_NUM));

    //
    // set CSn to Low for ADC1
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 0);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE, MODE_VALUE_RESET_SPI2);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE, MODE_VALUE_RESET_SPI1);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE, MODE_VALUE_RESET_SPI0);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    //
    // set CSn to High for ADC1
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 1);

    SysCtl_delay(10000);

    //
    // CSn to Low for ADC1
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 0);
    
    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              MODE_VALUE_PROGRAMMED_SPI2);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              MODE_VALUE_PROGRAMMED_SPI1);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              MODE_VALUE_PROGRAMMED_SPI0);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    //
    // set CSn to High for ADC1
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 1);

    SysCtl_delay(10000);

    //
    // CSn to Low for ADC1
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 0);
    
    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                               CLOCK_VALUE_PROGRAMMED_SPI2);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              CLOCK_VALUE_PROGRAMMED_SPI1);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              CLOCK_VALUE_PROGRAMMED_SPI0);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    //
    // set CSn to High for ADC1
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 1);

    SysCtl_delay(10000);
    
    // Now configure ADC2
    //
    //(REQUIRED) Configure MODE register settings for ADC2
    //
    while(!GPIO_readPin(AC3PH_EXT_ADC2_DRDY_GPIO_NUM));

    //
    // set CSn to Low for ADC2
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 0);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE, MODE_VALUE_RESET_SPI2);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE, MODE_VALUE_RESET_SPI1);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE, MODE_VALUE_RESET_SPI0);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    //
    // set CSn to High for ADC2
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 1);

    SysCtl_delay(10000);

    //
    // CSn to Low for ADC2
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 0);
    
    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              MODE_VALUE_PROGRAMMED_SPI2);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              MODE_VALUE_PROGRAMMED_SPI1);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              MODE_VALUE_PROGRAMMED_SPI0);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    //
    // set CSn to High for ADC2
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 1);

    SysCtl_delay(10000);

    //
    // CSn to Low for ADC2
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 0);
    
    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                               CLOCK_VALUE_PROGRAMMED_SPI2);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              CLOCK_VALUE_PROGRAMMED_SPI1);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    SPI_writeDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE,
                              CLOCK_VALUE_PROGRAMMED_SPI0);
    SPI_readDataBlockingFIFO(AC3PH_EXT_ADC_SPI_BASE);

    //
    // set CSn to High for ADC2
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 1);

    SysCtl_delay(10000);
}

void main(void)
{
    //
    // Initialize device clock and peripherals
    // Device clock is set 125MHz
    //
    Device_init();
    //
    // Disable pin locks and enable internal pullups.
    //
    Device_initGPIO();
    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();
    EALLOW;
    //
    // Clock for External ADC - GPIO pin configuration to EPWM
    //
    AC3PH_HAL_setupGpioExtAdcClk();
    //
    // Clock for External ADC- ePWM setup
    //
    AC3PH_HAL_disableEpwmCounting();
    AC3PH_HAL_setupEpwmExtAdcClk();
    AC3PH_HAL_enableEpwmCounting();
    //
    // Configure SPI for External ADCs
    // Initialize External ADCs
    //
    AC3PH_HAL_SetupSpiGpio();
    AC3PH_HAL_SetupSpi();
    AC3PH_HAL_setupGpioExtAdc();
    AC3PH_HAL_setupExtAdc();
    //
    // Initialize global variables used in the solution
    //
//    AC3PH_initUserVariables();
//    AC3PH_initProgramVariables();
//    AC3PH_setControlCoeffcients();
    //
    // Configure and enable External ADC dataready and SPI interrupts
    //
    AC3PH_HAL_setupExtAdcInterrupt();
    //discardFirstFrame = 1;
    AC3PH_HAL_enableExtAdcInterrupt();
    //
    // enable global interrupts
    //
    AC3PH_HAL_enableGlobalInterrupt();
    EDIS;
    //
    // Send initial ExtAdc transmit frames to both ADCs
    //
    // Set CS low for ADC1
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 0);
    // Send TX frame
    AC3PH_HAL_ExtAdcTxframe(AC3PH_EXT_ADC_SPI_BASE);
    // Set CS high
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 1);
    
    // Slight delay between ADCs
    SysCtl_delay(100);
    
    // Set CS low for ADC2
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 0);
    // Send TX frame
    AC3PH_HAL_ExtAdcTxframe(AC3PH_EXT_ADC_SPI_BASE);
    // Set CS high
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 1);
    
    for(;;)
    {
        // Main application code
        // Both ADCs will be handled by their respective interrupts
    }
}

#ifndef AC_METER_ADS131M0X_H_
#define AC_METER_ADS131M0X_H_
#ifdef __cplusplus
extern "C" {
#endif

// Maximum ADC clock frequency is 10MHz
// Maximum SPI clock frequency is 25MHz

//-----------------------------------------------------------------------------
// Data type to store ADS131M0x output (24-bit output)
//-----------------------------------------------------------------------------
typedef struct
{
    volatile uint16_t response;  // e.g. status bits
    volatile uint16_t crc;       // communication CRC
    volatile int32_t channel0;
    volatile int32_t channel1;
    volatile int32_t channel2;
    volatile int32_t channel3;
    volatile int32_t channel4;
    volatile int32_t channel5;
    volatile int32_t channel6;
    volatile int32_t channel7;
} ads131m0x_data;

// Global instances for External ADC1 and ADC2
extern ads131m0x_data EXT_ADC1;
extern ads131m0x_data EXT_ADC2;

//-----------------------------------------------------------------------------
// ADC OSR Setting
//-----------------------------------------------------------------------------
#define ADS131M0X_OSR   (4096U)

//-----------------------------------------------------------------------------
// Register Addresses per datasheet
//-----------------------------------------------------------------------------
#define ADDR_ID_REG        (0x00)
#define ADDR_STATUS_REG    (0x01)
#define ADDR_MODE_REG      (0x02)
#define ADDR_CLOCK_REG     (0x03)

//-----------------------------------------------------------------------------
// WREG command format (for writing registers)
// WREG command: 011a aaaa annn nnnn where "a aaaa a" is the starting register address
// and "nnn nnnn" is the number of registers to write minus one.
//-----------------------------------------------------------------------------
#define WREG_COMMAND_MODE   ((0x0003 << 13) | (ADDR_MODE_REG << 7))
#define WREG_COMMAND_CLOCK  ((0x0003 << 13) | (ADDR_CLOCK_REG << 7))
//-----------------------------------------------------------------------------
// RREG command format (for reading registers)
// RREG command: 101a aaaa annn nnnn where "a aaaa a" is the starting register address
// and "nnn nnnn" is the number of registers to read minus one.
//-----------------------------------------------------------------------------
#define RREG_COMMAND_ID     ((0x0005 << 13) | (ADDR_ID_REG << 7))
#define RREG_COMMAND_MODE   ((0x0005 << 13) | (ADDR_MODE_REG << 7))
//-----------------------------------------------------------------------------
// MODE register settings
//-----------------------------------------------------------------------------
#define REG_MODE_VALUE_RESET       (0x0501)
#define REG_MODE_VALUE_PROGRAMMED  (0x0001)

//-----------------------------------------------------------------------------
// CLOCK register settings
//-----------------------------------------------------------------------------
#define REG_CLOCK_VALUE_RESET      (0xFF0E)
#if (ADS131M0X_OSR == 128)
  #define REG_CLOCK_VALUE_PROGRAMMED  (0xFF43) // For 128 OSR
#elif (ADS131M0X_OSR == 256)
  #define REG_CLOCK_VALUE_PROGRAMMED  (0xFF47) // For 256 OSR
#elif (ADS131M0X_OSR == 512)
  #define REG_CLOCK_VALUE_PROGRAMMED  (0xFF4B) // For 512 OSR
#elif (ADS131M0X_OSR == 1024)
  #define REG_CLOCK_VALUE_PROGRAMMED  (0xFF4F) // For 1024 OSR
#elif (ADS131M0X_OSR == 4096)
  #define REG_CLOCK_VALUE_PROGRAMMED  (0xFF57) // For 4096 OSR
#else
  #error "This OSR setting is not supported. Correct ADS131M0X_OSR and recompile the project."
#endif

//-----------------------------------------------------------------------------
// SPI data mode definitions (for 24-bit output)
//-----------------------------------------------------------------------------
#define MODE_VALUE_RESET_SPI2       (WREG_COMMAND_MODE)
#define MODE_VALUE_RESET_SPI1       (REG_MODE_VALUE_RESET >> 8)
#define MODE_VALUE_RESET_SPI0       (REG_MODE_VALUE_RESET << 8)

#define MODE_VALUE_PROGRAMMED_SPI2  (WREG_COMMAND_MODE)
#define MODE_VALUE_PROGRAMMED_SPI1  (REG_MODE_VALUE_PROGRAMMED >> 8)
#define MODE_VALUE_PROGRAMMED_SPI0  (REG_MODE_VALUE_RESET << 8)

//-----------------------------------------------------------------------------
// ADC CLOCK setup macros
//-----------------------------------------------------------------------------
#define CLOCK_VALUE_PROGRAMMED_SPI2 (WREG_COMMAND_CLOCK)
#define CLOCK_VALUE_PROGRAMMED_SPI1 (REG_CLOCK_VALUE_PROGRAMMED)
#define CLOCK_VALUE_PROGRAMMED_SPI0 (0x0000)

//-----------------------------------------------------------------------------
//
// External ADC1 communication GPIO configuration
//
//-----------------------------------------------------------------------------

#define AC3PH_EXT_ADC1_SDIN_GPIO_NUM 24
#define AC3PH_EXT_ADC1_SDIN_PIN_CONFIG GPIO_24_SPIB_SIMO

#define AC3PH_EXT_ADC1_SDOUT_GPIO_NUM 25
#define AC3PH_EXT_ADC1_SDOUT_PIN_CONFIG GPIO_25_SPIB_SOMI

#define AC3PH_EXT_ADC1_SCLK_GPIO_NUM 26
#define AC3PH_EXT_ADC1_SCLK_PIN_CONFIG GPIO_26_SPIB_CLK

#define AC3PH_EXT_ADC1_CS_GPIO_NUM 53
#define AC3PH_EXT_ADC1_CS_PIN_CONFIG_GPIO GPIO_53_GPIO53

#define AC3PH_EXT_ADC1_DRDY_GPIO_NUM 51
#define AC3PH_EXT_ADC1_DRDY_PIN_CONFIG_GPIO GPIO_51_GPIO51

#define AC3PH_EXT_ADC1_RST_GPIO_NUM 41
#define AC3PH_EXT_ADC1_RST_PIN_CONFIG_GPIO GPIO_41_GPIO41

//-----------------------------------------------------------------------------
//
// External ADC2 communication GPIO configuration
//
//-----------------------------------------------------------------------------

// For ADC2, we'll use the same SPI interface (SPIB) but different CS and DRDY pins
#define AC3PH_EXT_ADC2_CS_GPIO_NUM 27
#define AC3PH_EXT_ADC2_CS_PIN_CONFIG_GPIO GPIO_27_GPIO27

#define AC3PH_EXT_ADC2_DRDY_GPIO_NUM 50
#define AC3PH_EXT_ADC2_DRDY_PIN_CONFIG_GPIO GPIO_50_GPIO50

// Using the same reset pin for ADC2 as ADC1 (you may want to use a separate pin if available)
#define AC3PH_EXT_ADC2_RST_GPIO_NUM AC3PH_EXT_ADC1_RST_GPIO_NUM
#define AC3PH_EXT_ADC2_RST_PIN_CONFIG_GPIO AC3PH_EXT_ADC1_RST_PIN_CONFIG_GPIO

//
// External ADC1 DRDY Interrupt configuration
//
#define AC3PH_EXT_ADC1_INT_DRDY INT_XINT1
#define AC3PH_EXT_ADC1_ISR_DRDY ISR4
#define AC3PH_EXT_ADC1_INT_DRDY_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP1

//
// External ADC2 DRDY Interrupt configuration
//
#define AC3PH_EXT_ADC2_INT_DRDY INT_XINT2
#define AC3PH_EXT_ADC2_ISR_DRDY ISR5
#define AC3PH_EXT_ADC2_INT_DRDY_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP1

//
// External ADC SPI Interrupt configuration
//
#define AC3PH_EXT_ADC_SPI_CLOCK_FREQ_HZ         (2000000U)
#define AC3PH_EXT_ADC_SPI_BASE SPIB_BASE
#define AC3PH_EXT_ADC_INT_SPI_RX INT_SPIB_RX
#define AC3PH_EXT_ADC1_ISR_SPI_RXFIFO ISR7
#define AC3PH_EXT_ADC2_ISR_SPI_RXFIFO ISR8
#define AC3PH_EXT_ADC_SPI_RXFIFO_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP6

extern ads131m0x_data AC3PH_ExtAdc1;
extern ads131m0x_data AC3PH_ExtAdc2;
extern volatile uint16_t AC3PH_ExtAdcRxflag1;
extern volatile uint16_t AC3PH_ExtAdcRxflag2;
extern volatile int32_t ads131m08_adc1_latestSamples[8];
extern volatile int32_t ads131m08_adc2_latestSamples[8];

// Function declarations
void AC3PH_HAL_setupGpioExtAdcClk(void);
void AC3PH_HAL_SetupSpiGpio(void);
void AC3PH_HAL_SetupSpi(void);
void AC3PH_HAL_setupGpioExtAdc(void);
void AC3PH_HAL_setupExtAdc(void);
void AC3PH_HAL_setupExtAdcInterrupt(void);
void AC3PH_HAL_enableExtAdcInterrupt(void);
void AC3PH_HAL_enableGlobalInterrupt(void);
void AC3PH_HAL_GpioWrite(uint32_t GPIO_NUM, uint16_t state);

__interrupt void ISR4(void);  // ADC1 DRDY interrupt
__interrupt void ISR5(void);  // ADC2 DRDY interrupt
__interrupt void ISR7(void);  // ADC1 SPI RX interrupt
__interrupt void ISR8(void);  // ADC2 SPI RX interrupt

static inline void AC3PH_HAL_ExtAdcTxframe(uint32_t base){
    //send bytes for N channel data read
    uint16_t crcWordIn = 0;
    // send null word
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    //send CRC if enabled, otherwise write 0
    HWREGH(base + SPI_O_TXBUF) = crcWordIn;

    //send rest 8 words
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
    HWREGH(base + SPI_O_TXBUF) = 0x0000;
}

static inline void AC3PH_HAL_ExtAdcRxframe(ads131m0x_data *DataStruct,
                                           uint32_t base){
    //
    // read from the buffer
    //
    DataStruct->response = HWREGH(base + SPI_O_RXBUF);

    DataStruct->channel0 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel1 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel2 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel3 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel4 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel5 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel6 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->channel7 = HWREGH(base + SPI_O_RXBUF);
    DataStruct->crc = HWREGH(base + SPI_O_RXBUF);
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_ExtAdc1SendTxFrame)
static inline void AC3PH_HAL_ExtAdc1SendTxFrame(void){
    //
    // data is available in the FIFO to read
    //
    if(AC3PH_ExtAdcRxflag1 == 1)
    {
        AC3PH_ExtAdcRxflag1 = 0;

        //
        // make cs low and send the data
        //
        GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 0);

        //
        //send command to read data
        //
        AC3PH_HAL_ExtAdcTxframe(AC3PH_EXT_ADC_SPI_BASE);
    }
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_ExtAdc2SendTxFrame)
static inline void AC3PH_HAL_ExtAdc2SendTxFrame(void){
    //
    // data is available in the FIFO to read
    //
    if(AC3PH_ExtAdcRxflag2 == 1)
    {
        AC3PH_ExtAdcRxflag2 = 0;

        //
        // make cs low and send the data
        //
        GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 0);

        //
        //send command to read data
        //
        AC3PH_HAL_ExtAdcTxframe(AC3PH_EXT_ADC_SPI_BASE);
    }
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_DrdyGpio1AckInterrupt)
static inline void AC3PH_HAL_DrdyGpio1AckInterrupt(void){
    Interrupt_clearACKGroup(AC3PH_EXT_ADC1_INT_DRDY_INTERRUPT_ACK_GROUP);
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_DrdyGpio2AckInterrupt)
static inline void AC3PH_HAL_DrdyGpio2AckInterrupt(void){
    Interrupt_clearACKGroup(AC3PH_EXT_ADC2_INT_DRDY_INTERRUPT_ACK_GROUP);
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_ExtAdc1Read)
static inline void AC3PH_HAL_ExtAdc1Read(){
    //
    // make cs high
    //
    GPIO_writePin(AC3PH_EXT_ADC1_CS_GPIO_NUM, 1);
    AC3PH_HAL_ExtAdcRxframe(&AC3PH_ExtAdc1, AC3PH_EXT_ADC_SPI_BASE);

    // Copy to sample buffer
    ads131m08_adc1_latestSamples[0] = AC3PH_ExtAdc1.channel0;
    ads131m08_adc1_latestSamples[1] = AC3PH_ExtAdc1.channel1;
    ads131m08_adc1_latestSamples[2] = AC3PH_ExtAdc1.channel2;
    ads131m08_adc1_latestSamples[3] = AC3PH_ExtAdc1.channel3;
    ads131m08_adc1_latestSamples[4] = AC3PH_ExtAdc1.channel4;
    ads131m08_adc1_latestSamples[5] = AC3PH_ExtAdc1.channel5;
    ads131m08_adc1_latestSamples[6] = AC3PH_ExtAdc1.channel6;
    ads131m08_adc1_latestSamples[7] = AC3PH_ExtAdc1.channel7;

    //
    // flag to hold receive is complete
    //
    AC3PH_ExtAdcRxflag1 = 1;
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_ExtAdc2Read)
static inline void AC3PH_HAL_ExtAdc2Read(){
    //
    // make cs high
    //
    GPIO_writePin(AC3PH_EXT_ADC2_CS_GPIO_NUM, 1);
    AC3PH_HAL_ExtAdcRxframe(&AC3PH_ExtAdc2, AC3PH_EXT_ADC_SPI_BASE);

    // Copy to sample buffer
    ads131m08_adc2_latestSamples[0] = AC3PH_ExtAdc2.channel0;
    ads131m08_adc2_latestSamples[1] = AC3PH_ExtAdc2.channel1;
    ads131m08_adc2_latestSamples[2] = AC3PH_ExtAdc2.channel2;
    ads131m08_adc2_latestSamples[3] = AC3PH_ExtAdc2.channel3;
    ads131m08_adc2_latestSamples[4] = AC3PH_ExtAdc2.channel4;
    ads131m08_adc2_latestSamples[5] = AC3PH_ExtAdc2.channel5;
    ads131m08_adc2_latestSamples[6] = AC3PH_ExtAdc2.channel6;
    ads131m08_adc2_latestSamples[7] = AC3PH_ExtAdc2.channel7;

    //
    // flag to hold receive is complete
    //
    AC3PH_ExtAdcRxflag2 = 1;
}

#pragma FUNC_ALWAYS_INLINE(AC3PH_HAL_SpiRxFifoAckInterrupt)
static inline void AC3PH_HAL_SpiRxFifoAckInterrupt(){
    SPI_clearInterruptStatus(AC3PH_EXT_ADC_SPI_BASE, SPI_INT_RXFF);
    Interrupt_clearACKGroup(AC3PH_EXT_ADC_SPI_RXFIFO_INTERRUPT_ACK_GROUP);
}

#ifdef __cplusplus
}
#endif
#endif /* AC_METER_ADS131M0X_H_ */



  • Hi Dale,

    Yes, you are right — SPIB_RX is connected to the DOUT signal of the ADS131M08 ADC.

    In our design, we have two ADS131M08 ICs connected to the same SPIB peripheral of the MCU, each with its own dedicated chip select (CS) line.

    Regarding the interrupt usage — we followed TI's TIDA-010087 reference design, where ISR7 is used for handling the DRDY signal. Based on your observation, are you suggesting that ISR8 may not be necessary in our case? That would be helpful to confirm.

    For clarity, I’ve attached the schematic and a logic analyzer capture showing the SPI bus activity along with the DRDY signal.

    Please let me know your thoughts after reviewing them.







    Best regards,
    Ramakrishna

  • Hi Ramakrishna,

    Thanks for reaching out to me in emails.

    As per our communications via your emails, if you have any questions about the reference design, you can ask the SEM team here.

    If you have any questions about the ADS131M08 device, you can post your query on the data-converters-forum. Actually I already communicated with you about the procedure how to read the data from ADS131M08.

    Regards,

    Dale