Tool/software:
Facing issue to interface TI ADC chip ADS131m08 with my MICRO TMS320F28388S.
Here I am attaching my complete code for reference .
I am using ADS131M08EVM with my MICRO and giving AVDD and DVDD 3.3v from my MICRO. For confirmation I am using existing internal crystal of EVM and setting it to 8.192 MHZ.
Issue is DRDY PIN not triggering my micro interrupt and if I am trying to read data without DRDY interrupt synchronization, then not receiving correct data.
Another problem I facing whatever I am writing to register ,when I am reading back not getting same value. Added my console output also.
Where I am doing wrong , I need immediate help . Attched DRDY pin signal captured in Scope.
[C28xx_CPU1] SPI configured at 8000000 Hz (target 8000000 Hz) Configuring ADS131M08 registers... Sending Command: 0x0011 Received Response: 0x7F11 Sending Command: 0x0655 Received Response: 0x7F00 UNLOCK command successful. Writing Register 0x03, Command: 0x6180, Value: 0x0F0E Received Response: 0x7F55 Received Response: 0x7F00 Received Response: 0x7F80 Read Register 0x03: 0x0080 Register 0x03 write mismatch: wrote 0x0F0E, read 0x0080 Received Response: 0x8F0E Received Response: 0xF2A1 Received Response: 0x8080 Read Register 0x03: 0x0080 Clock Register MISMATCH: wrote 0x0F0E, read 0x0080 Writing Register 0x02, Command: 0x6100, Value: 0x0510 Received Response: 0x0000 Received Response: 0x7F00 Received Response: 0x7F00 Read Register 0x02: 0x0000 Register 0x02 write mismatch: wrote 0x0510, read 0x0000 Received Response: 0x7FA1 Received Response: 0x9480 Received Response: 0x0000 Read Register 0x02: 0x0000 Mode Register MISMATCH: wrote 0x0510, read 0x0000 Writing Register 0x04, Command: 0x6200, Value: 0x0000 Received Response: 0x7F00 Received Response: 0x8F10 Received Response: 0xF2A1 Read Register 0x04: 0x00A1 Register 0x04 write mismatch: wrote 0x0000, read 0x00A1 Received Response: 0x7F00 Received Response: 0x7F00 Received Response: 0x7FA1 Read Register 0x04: 0x00A1 Gain Register MISMATCH: wrote 0x0000, read 0x00A1
#include "device.h" #include "driverlib.h" #include <string.h> // ADS131M08 Commands #define ADS131M08_CMD_NULL 0x0000 // No operation (used for reading data) #define ADS131M08_CMD_RESET 0x0011 // Reset #define ADS131M08_CMD_STANDBY 0x0022 // Enter standby mode #define ADS131M08_CMD_WAKEUP 0x0033 // Exit standby mode #define ADS131M08_CMD_LOCK 0x0555 // Lock registers #define ADS131M08_CMD_UNLOCK 0x0655 // Unlock registers // Define register addresses #define ADS131M08_REG_ID 0x00 // ID register #define ADS131M08_REG_STATUS 0x01 // Status register #define ADS131M08_REG_MODE 0x02 // Mode register #define ADS131M08_REG_CLOCK 0x03 // Clock register // ADS131M08 frame structure (for 8 channels) // Each frame consists of: Status word (2 bytes) + 8 channels (3 bytes each) + CRC (2 bytes) = 28 bytes #define ADS131M08_FRAME_SIZE 28 #define ADS131M08_CHANNELS 8 // DMA definitions #define ADC_DMA_TX DMA_CH1_BASE #define ADC_DMA_RX DMA_CH2_BASE // GPIO definitions #define ADC_CS_PIN 11 #define ADC_RESET_PIN 37 #define ADC_DRDY_PIN 35 // Define memory buffers for ADC data #pragma DATA_SECTION(adcRxBuffer, "ramgs0"); volatile uint16_t adcRxBuffer[ADS131M08_FRAME_SIZE/2]; // 16-bit words for SPI transfer (28 bytes = 14 words) #pragma DATA_SECTION(adcTxBuffer, "ramgs1"); volatile uint16_t adcTxBuffer[ADS131M08_FRAME_SIZE/2]; // TX buffer with NULL commands // Processing buffer for converted data volatile int32_t channelData[ADS131M08_CHANNELS]; volatile uint16_t statusWord; volatile bool newDataReady = false; volatile bool dmaTransferComplete = true; // Function prototypes void ADS131M08_init(void); void configureDMA(void); void processADCData(void); __interrupt void DRDY_ISR(void); __interrupt void DMA_RX_ISR(void); void ADS131M08_init(void) { uint16_t i; // Enable clock for SPIA and DMA SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA); SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DMA); // Configure SPI pins GPIO_setPinConfig(GPIO_16_SPIA_SIMO); GPIO_setPinConfig(GPIO_17_SPIA_SOMI); GPIO_setPinConfig(GPIO_18_SPIA_CLK); // Configure CS pin as output GPIO_setPadConfig(ADC_CS_PIN, GPIO_PIN_TYPE_STD); GPIO_setDirectionMode(ADC_CS_PIN, GPIO_DIR_MODE_OUT); GPIO_writePin(ADC_CS_PIN, 1); // Initialize CS high // Configure RESET/SYNC pin as output GPIO_setPadConfig(ADC_RESET_PIN, GPIO_PIN_TYPE_STD); GPIO_setDirectionMode(ADC_RESET_PIN, GPIO_DIR_MODE_OUT); GPIO_writePin(ADC_RESET_PIN, 1); // Initialize RESET high // Configure SPIA module - ADS131M08 requires CPOL=0, CPHA=1 (MODE 1) // Maximum SPI clock for ADS131M08 is 20MHz SPI_setConfig(SPIA_BASE, DEVICE_SYSCLK_FREQ, SPI_PROT_POL0PHA1, SPI_MODE_MASTER, 8000000, 16); // 8MHz clock, 16-bit words // Configure FIFO for optimal DMA operation SPI_enableFIFO(SPIA_BASE); SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX4, SPI_FIFO_RX4); // Enable SPI module SPI_enableModule(SPIA_BASE); // Configure DRDY pin as input with falling edge interrupt GPIO_setPadConfig(ADC_DRDY_PIN, GPIO_PIN_TYPE_PULLUP); GPIO_setDirectionMode(ADC_DRDY_PIN, GPIO_DIR_MODE_IN); GPIO_setInterruptPin(ADC_DRDY_PIN, GPIO_INT_XINT1); GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_FALLING_EDGE); // Initialize PIE and enable interrupts Interrupt_initModule(); Interrupt_initVectorTable(); // Register interrupt handlers Interrupt_register(GPIO_INT_XINT1, DRDY_ISR); Interrupt_register(INT_DMA_CH2, DMA_RX_ISR); // Associate DMA RX complete with INT_DMA_CH2 // Initialize TX buffer with NULL commands for(i = 0; i < ADS131M08_FRAME_SIZE/2; i++) { adcTxBuffer[i] = ADS131M08_CMD_NULL; } // Configure DMA configureDMA(); // Reset ADS131M08 GPIO_writePin(ADC_RESET_PIN, 0); DEVICE_DELAY_US(10); // 10 μs delay (minimum required) //GPIO_writePin(ADC_RESET_PIN, 1); DEVICE_DELAY_US(200); // Wait for ADC to stabilize after reset // Send initial configuration commands to ADS131M08 // Assert CS GPIO_writePin(ADC_CS_PIN, 0); // Issue UNLOCK command SPI_writeDataBlockingFIFO(SPIA_BASE, ADS131M08_CMD_UNLOCK); SPI_readDataBlockingFIFO(SPIA_BASE); // Read and discard response // Write to MODE register (configure word length, CRC, etc.) SPI_writeDataBlockingFIFO(SPIA_BASE, 0x4002); // Write to MODE register (0x02) SPI_readDataBlockingFIFO(SPIA_BASE); // Read and discard response SPI_writeDataBlockingFIFO(SPIA_BASE, 0x0510); // Example: 24-bit word length SPI_readDataBlockingFIFO(SPIA_BASE); // Read and discard response // Write to CLOCK register (enable all channels, set OSR, etc.) SPI_writeDataBlockingFIFO(SPIA_BASE, 0x4003); // Write to CLOCK register (0x03) SPI_readDataBlockingFIFO(SPIA_BASE); // Read and discard response SPI_writeDataBlockingFIFO(SPIA_BASE, 0x0FF0); // Enable all 8 channels, OSR=512 SPI_readDataBlockingFIFO(SPIA_BASE); // Read and discard response // Deassert CS GPIO_writePin(ADC_CS_PIN, 1); // Enable DMA and DRDY interrupts Interrupt_enable(INT_DMA_CH2); Interrupt_enable(GPIO_INT_XINT1); // Enable global interrupts Interrupt_enableMaster(); } void configureDMA(void) { // Initialize DMA controller DMA_initController(); // Configure DMA TX channel DMA_configAddresses(ADC_DMA_TX, (uint16_t*)adcTxBuffer[0], (uint16_t*)(SPIA_BASE + SPI_O_TXBUF)); DMA_configBurst(ADC_DMA_TX, 1, 1, 0); // Burst size 1 word, src increment 1, dest no increment DMA_configTransfer(ADC_DMA_TX, ADS131M08_FRAME_SIZE/2, 1, 0); // Transfer size is frame size, same increments DMA_configMode(ADC_DMA_TX, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_ENABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT); // Configure DMA RX channel DMA_configAddresses(ADC_DMA_RX, (uint16_t*)(SPIA_BASE + SPI_O_RXBUF), (uint16_t*)adcRxBuffer[0]); DMA_configBurst(ADC_DMA_RX, 1, 0, 1); // Burst size 1 word, src no increment, dest increment 1 DMA_configTransfer(ADC_DMA_RX, ADS131M08_FRAME_SIZE/2, 0, 1); // Transfer size is frame size, same increments DMA_configMode(ADC_DMA_RX, DMA_TRIGGER_SPIARX, DMA_CFG_ONESHOT_ENABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT); // Configure DMA RX to trigger an interrupt when complete DMA_setInterruptMode(ADC_DMA_RX, DMA_INT_AT_END); DMA_enableInterrupt(ADC_DMA_RX); } __interrupt void DRDY_ISR(void) { // Clear GPIO interrupt flag //XINT_clearInterruptFlag(GPIO_INT_XINT1); // Only start a new transfer if previous one has completed if (dmaTransferComplete) { // Assert CS GPIO_writePin(ADC_CS_PIN, 0); // Reset DMA source and destination pointers DMA_configAddresses(ADC_DMA_TX, (uint16_t*)adcTxBuffer[0], (uint16_t*)(SPIA_BASE + SPI_O_TXBUF)); DMA_configAddresses(ADC_DMA_RX, (uint16_t*)(SPIA_BASE + SPI_O_RXBUF), (uint16_t*)adcRxBuffer[0]); // Set transfer counts DMA_configTransfer(ADC_DMA_TX, ADS131M08_FRAME_SIZE/2, 1, 0); DMA_configTransfer(ADC_DMA_RX, ADS131M08_FRAME_SIZE/2, 0, 1); // Start DMA channels dmaTransferComplete = false; DMA_startChannel(ADC_DMA_RX); // Start RX channel first DMA_startChannel(ADC_DMA_TX); // Then start TX channel DMA_forceTrigger(ADC_DMA_TX); // Force trigger the TX DMA } // Acknowledge PIE interrupt Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); } __interrupt void DMA_RX_ISR(void) { uint16_t i, j; uint8_t *dataPtr; // Deassert CS GPIO_writePin(ADC_CS_PIN, 1); // Extract status word (first word in the frame) statusWord = adcRxBuffer[0]; // Extract channel data (24-bit values stored in 16-bit words) // Each channel has 3 bytes (24 bits) starting from byte index 2 (after status word) dataPtr = (uint8_t*)&adcRxBuffer[1]; // Point to byte after status word for(i = 0; i < ADS131M08_CHANNELS; i++) { // Extract 24-bit data for this channel int32_t rawData = ((int32_t)dataPtr[i*3] << 16) | ((int32_t)dataPtr[i*3+1] << 8) | ((int32_t)dataPtr[i*3+2]); // Sign extend from 24-bit to 32-bit if(rawData & 0x800000) { rawData |= 0xFF000000; } channelData[i] = rawData; } // Set flags dmaTransferComplete = true; newDataReady = true; // Clear DMA interrupt flag DMA_clearTriggerFlag(ADC_DMA_RX); // Acknowledge PIE interrupt Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7); // DMA interrupts are in group 7 } void processADCData(void) { uint16_t i; // Process each channel's data for(i = 0; i < ADS131M08_CHANNELS; i++) { // Example: Convert to voltage (assuming ±2.5V reference) float voltage = (float)channelData[i] * (5.0f / 8388608.0f); // 24-bit data to voltage // Do something with the voltage value // Example: Apply calibration, filtering, etc. } } void main(void) { // Initialize system clock and peripherals Device_init(); Device_initGPIO(); // Initialize ADS131M08 interface ADS131M08_init(); while(1) { if(newDataReady) { // Process ADC data processADCData(); // Clear flag newDataReady = false; } // Other system tasks can go here } }
Hi Ramakrishna,
Apologies for the delay. I'm looking into this issue further and will get back to you as soon as possible.
Best Regards,
Aishwarya
Hi Aishwarya,
Thanks for your response.
Looking forward to your prompt support, as this is a critical part of our project.
Regards,
Ramakrishna