2020-03-25 05:01 AM
Hi everyone,
I work on Data Acquisition System project. Our main controller is STM32F765VG. We used ADS131A0x A/D converter (by SPI) to sample input signal in our previous version. Now we want to replace ADS131A0x with ADS1274 (because of its higher sampling rate).
I haven’t encountered any problem when I get data from ADS131A0x through SPI-DMA combination.
I couldn’t use SPI with ADS1274 because of its high sampling rate. So I decided to use SAI interface. It is completely suitable with ADS1274 and I didn’t have any problem (I could get interrupt from DMA and obtain SAI data that transferred by DMA). But when I plotted 1024 samples, I saw that some samples are absent. And then, I collected more samples by Saleae Logic Pro. and compared them.
As you see from picture abowe, there are some absent samples (with STM32F765VG).
As you see from picture abowe, there isn't any absent sample ( with Saleae Logic Pro.).
I think, my DMA gives me wrong data sometimes or it misses some samples.
I used CubeMX to generate codes for SAI-DMA. Here my settings :
volatile sint32_t adsRdBuf[1];
SAI_HandleTypeDef hsai_BlockA1;
DMA_HandleTypeDef hdma_sai1_a;
void initASAI1(void)
{
#if(!ADS1274_SAI1A_USE_DMA)
IRQ_attach(ADS1274_SAI1A_SAI_IRQ, IRQ_RESOURCE_ADS1274_SAI1A_SAI, IRQ_ENABLE);
#endif
// SAI1
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
hsai_BlockA1.Init.DataSize = SAI_DATASIZE_24;
hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;
hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_96K;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.FrameInit.FrameLength = 32;
hsai_BlockA1.FrameInit.ActiveFrameLength= 1;
hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
hsai_BlockA1.SlotInit.FirstBitOffset = 0;
hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA1.SlotInit.SlotNumber = 1;
hsai_BlockA1.SlotInit.SlotActive = SAI_SLOTACTIVE_0;
HAL_SAI_Init(&hsai_BlockA1);
}
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
GPIO_InitTypeDef gis;
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_SAI1_CLK_ENABLE();
/**SAI1_A_Block_A GPIO Configuration
PE2 ------> SAI1_MCLK_A
PE4 ------> SAI1_FS_A
PE5 ------> SAI1_SCK_A
PE6 ------> SAI1_SD_A
*/
gis.Pin = LL_GPIO_PIN_6| LL_GPIO_PIN_5| LL_GPIO_PIN_4| LL_GPIO_PIN_2;
gis.Mode = GPIO_MODE_AF_PP;
gis.Pull = GPIO_NOPULL;
gis.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
gis.Alternate = GPIO_AF6_SAI1;
HAL_GPIO_Init(GPIOE, &gis);
#if(ADS1274_SAI1A_USE_DMA)
// Peripheral DMA init
hdma_sai1_a.Instance = DMA2_Stream6;
hdma_sai1_a.Init.Channel = LL_DMA_CHANNEL_10;
hdma_sai1_a.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;
hdma_sai1_a.Init.PeriphDataAlignment= DMA_PDATAALIGN_WORD;
hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sai1_a.Init.Mode = DMA_CIRCULAR;
hdma_sai1_a.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_sai1_a);
__HAL_LINKDMA(hsai,hdmarx,hdma_sai1_a);
#endif
}
void startADS1274(void)
{
#if(ADS1274_SAI1A_USE_DMA)
HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t *)&(adsRdBuf[0]), ADS1274_READ_LEN);
#else
HAL_SAI_Receive_IT(&hsai_BlockA1, (uint8_t *)&(adsRdBuf[0]), 1);
#endif
}
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
{
sint32_t rd1;
rd1 = adsRdBuf[0];
if(rd1 >= ADS1274_VAL_LIM) {
V = (float32_t)rd1 - (float32_t)ADS1274_VAL_MAX;
} else {
V = (float32_t)rd1;
}
vBuf[rdCtr] = V;
rdCtr++;
if(rdCtr == 1024) {
rdCtr = 0;
}
#if(!ADS1274_SAI1A_USE_DMA)
HAL_SAI_Receive_IT(&hsai_BlockA1, (uint8_t *)&(adsRdBuf[0]), 1);
#endif
}
As you see in code below, I also tried to use SAI without DMA but the result was same.
Thanks for your comments and helps.
2020-04-01 09:45 AM
Most likely it's not the hardware, but something stupid in HAL code. Also make sure you have cache management and/or MPU configuration right. Try using FIFO on both - SAI and DMA.
2020-05-03 11:49 PM
Thanks for your reply @Piranha. I solved it. The problem is related with adding break point while system runs. I did many different tests. So I realized that if I double clicked line 104 to add break point while system runs, vBuf is bad (as I mentioned before). But if I click pause button, I saw that vBuf is perfect (as I expected). As a result I decided that I won't double click to add break point while system runs.