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_ */