2021-03-06 10:46 AM
Hello,
I am building and electric field sensor. The driver signal for it is produced via DAC of the STM32F767zi microcontroller. The signal is 4 kHz and is generated at a sampling speed of 80 kHz via DMA and TIM6. As you can see from the picture the signal has errors in it like every 10-20 wavelengths there is 1 corrupted sample.
Best regards
Solved! Go to Solution.
2021-03-07 01:04 PM
The solution for the problem was changing the callback functions to:
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
//first half of adc is full
inbufPtr= &adc_val[0];
outbufPtr= &dac_val[0];
processDSP();
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
inbufPtr= &adc_val[DATASIZE];
outbufPtr= &dac_val[DATASIZE];
processDSP();
}
cant really tell why this solved the problem. Occasionally it still happens that 1 sample is pulled high but it can be tolerated.
2021-03-06 03:05 PM
Hello
seems like interruption from a higher priority interrupt routines causes DMA underruns.
2021-03-06 11:31 PM
But would underrun result in an unexpected value to be output? Wouldn't it produce a "stretch" rather than a "glitch"?
I don't think this can be solved without seeing substantial portion of the code.
JW
2021-03-07 12:52 AM
The code is simple I load values of a cosine table into the DMA buffer. My first thought was that the DAC hit its limit regarding speed. 80kHz maybe too fast.
2021-03-07 01:51 AM
I have done further measurements, the DMA halfbuffer length is 1024. I have 20 samples for one wavelength. 1024/20 results in 51,2 Wave lengths per halfbuffer. When I measure on the oscilloscope the glitch happens exactly at every 51,2 wavelengths. Could it be that the DMA does something strange?
Here is the code for the DMA init:
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
for the DMA callback:
//callback functions
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
//first half of adc is full
inbufPtr= &adc_val[0];
outbufPtr= &dac_val[DATASIZE];
processDSP();
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
inbufPtr= &adc_val[DATASIZE];
outbufPtr= &dac_val[0];
processDSP();
}
and the DSP function where the DMA is filled:
void processDSP(void)
{
/*update buffers and and NCOs-------------------*/
for(int i=0;i<DATASIZE;i++)
{
//fill output buffer
outbufPtr[i]=(int)(2048+1000*cos_table[nco_f0.index]);
//read input into a buffer
incomming_buffer[i]=(float)inbufPtr[i]*ADC_gain; //ADC_gain=3.3/4095
//update local cosine and sine buffers
local_cosine_buffer[i]=cos_table[nco_f0.index];
local_sine_buffer[i]=-sin_table[nco_f0.index];
local_rect_buffer[i]=rect_table[nco_f0.index];
//update NCO
update_NCO(&nco_f0, COSINE_TABLE_SIZE);
}
I hope you can help
Regards
2021-03-07 10:52 AM
Is D-cache turned on? Is it managed properly?
2021-03-07 10:57 AM
Isn't the first or last value in the calculated array off? Read it out and check.
JW
2021-03-07 01:04 PM
The solution for the problem was changing the callback functions to:
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
//first half of adc is full
inbufPtr= &adc_val[0];
outbufPtr= &dac_val[0];
processDSP();
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
inbufPtr= &adc_val[DATASIZE];
outbufPtr= &dac_val[DATASIZE];
processDSP();
}
cant really tell why this solved the problem. Occasionally it still happens that 1 sample is pulled high but it can be tolerated.