Other Parts Discussed in Thread: ADS131A04
Hello! I am using MSP432 to communicate with ADS131A04 ADC and I want to use the ADC at 10.24kHz data rate.
The problem is that I cannot read the channel data fast enough before new data is available. At 10.24kHz, I need to read in maximum ~100us. In the read function I wait in a while loop for the next DRDY interrupt.
I have attached the following logic analyzer captures (they can be opened using the free Salae Logic Pro software; channel 4 is DRDY):
1. 1kHz data rate, 1MHz SPI clock - byte time is 8us, time between bytes is ~8us and word time ~314us;
2. 1kHz data rate, 4MHz SPI clock - byte time is 4us, time between bytes is ~10us and word time ~253us;
3. 1kHz data rate, 8MHz SPI clock - byte time is 1us, time between bytes is ~7us and word time ~170us;
4. 10.24kHz data rate, 8MHz SPI clock - byte time is 1us, time between bytes is ~7us and word time ~170us; you can see that DRDY changes before reading all data;
You can find attached an oscilloscope screen capture showing MISO at 1kHz data rate, 24MHz SPI clock. Those lines are the 20 bytes that compose the word and the transmission duration of a word is ~170us.
I need to have a word transmission time smaller than 100us to be able to read the next samples in time. 24MHz is the maximum SPI clock MSP432 can provide and 25MHz is the maximum SPI clock accepted by the ADC. 7us means 336 cycles for MSP432 at 48MHz. Where are these cycles spent?
This is my code:
for (i = 0; i < noSamples; i++)
{
while (adcSampleAvailable == false) // Wait for !DRDY
{
//MAP_PCM_gotoLPM0InterruptSafe();
//MAP_Interrupt_enableMaster();
}
adcSampleAvailable = false;
// Read samples
rxData = ADS131A04_read(20); // STAT_1 x 4 bytes + 4 channels x 4 bytes
*(readDataCh1 + i) = (*(rxData + 4) << 16) | (*(rxData + 5) << 8) | (*(rxData + 6));
*(readDataCh2 + i) = (*(rxData + 8) << 16) | (*(rxData + 9) << 8) | (*(rxData + 10));
*(readDataCh3 + i) = (*(rxData + 12) << 16) | (*(rxData + 13) << 8) | (*(rxData + 14));
*(readDataCh4 + i) = (*(rxData + 16) << 16) | (*(rxData + 17) << 8) | (*(rxData + 18));
}
unsigned char* ADS131A04_read(unsigned char bytesNumber)
{
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN4); // !ADC_SPI_CS = 0
int byte = 0;
int count = bytesNumber;
if (bytesNumber > ADS131A04_MAX_RX_BYTES) count = ADS131A04_MAX_RX_BYTES;
for(byte = 0; byte < count; byte++)
{
while (adcTxFlag == false)
{
//MAP_PCM_gotoLPM0InterruptSafe();
//MAP_Interrupt_enableMaster();
}
adcTxFlag = false;
MAP_SPI_transmitData(EUSCI_B0_BASE, 0x00); // Dummy write to clock out data
while (adcRxFlag == false)
{
//MAP_PCM_gotoLPM0InterruptSafe();
//MAP_Interrupt_enableMaster();
}
adcRxFlag = false;
rxData[byte] = MAP_SPI_receiveData(EUSCI_B0_BASE);
}
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN4); // !ADC_SPI_CS = 1
return rxData;
}
void PORT4_IRQHandler(void)
{
uint32_t status;
status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P4);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P4, status);
if(status & GPIO_PIN0) // ADC !DRDY
{
if (MAP_GPIO_getInputPinValue(GPIO_PORT_P4, GPIO_PIN0) == 0)
{
adcSampleAvailable = true;
MAP_Interrupt_disableSleepOnIsrExit();
}
}
}
void EUSCIB0_IRQHandler(void)
{
unsigned int status;
status = MAP_SPI_getEnabledInterruptStatus(EUSCI_B0_BASE);
MAP_SPI_clearInterruptFlag(EUSCI_B0_BASE, status);
if (status & EUSCI_B_SPI_TRANSMIT_INTERRUPT)
{
adcTxFlag = true;
}
if (status & EUSCI_B_SPI_RECEIVE_INTERRUPT)
{
adcRxFlag = true;
}
MAP_Interrupt_disableSleepOnIsrExit();
}
What can I do to read the data faster? Is it a limitation of MSP432?