3

I'm trying to compute the FFT of a 100 kHz signal from the STM32f746G discovery board using the HAL and CMSIS DSP libraries and I've run into a few issues.

My first issue was trying to trigger the ADC conversion using a Timer2 Trigger Update but it seems there's an issue with Timer2 TRGO based on section 2.2.1 of the errata sheet here. I finally got it to work using Timer 1 with the following settings.

static void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;   // 1 Msps Sampling rate.
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

And my Timer setup looks like this:

static void MX_TIM1_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = ((SystemCoreClock/2) / 100000) - 1;  // APB1 Timer clock is HCLK/2 for 100 Khz signal. 
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

My issue is when I start DMA and try to populate a buffer, only part of the array is populated and this seems to happen at random. I've come across something similar here but the suggestion of setting hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD and initialising the buffer to uint32_t doesn't seem to work for me. A sample output of my buffer looks like this: buffer output

My main function looks like this:

uint32_t ADC1ConvertedValue_s[2048];
 uint32_t ConvertedValue_s[2048];
 int endConv;
 \\initialise Timers and ADCs
 HAL_TIM_Base_Start(&htim1);
 HAL_ADC_Start_DMA(&hadc1, ADC1ConvertedValue_s, 2048);
 while (1)
  {
         if(endConv == 1)
         {
             HAL_TIM_Base_Stop(&htim1);
             HAL_ADC_Stop_DMA(&hadc1);

         }  
  }

And I copy the values in the HAL_ADC_ConvCpltCallback

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
 UNUSED(hadc);
    endConv = 1;

     for(i= 0; i< 2048; i++)
    {

        ConvertedValue_s[index_fill_adc_buffer] = 
        ADC1ConvertedValue_s[index_fill_adc_buffer];

    }

 }

Where am I going wrong here? I think the timer Period and Prescaler values are fine so I'm not sure that's the issue. I also think the ADC sampling rate of 1 Msps is correct and more than adequate. I've been tearing my head out trying to figure this out and some help would be appreciated.

  • Why are you using the ADC-complete callback and not the DMA-complete callback? ADC-complete will occur after each sample, while DMA-complete will occur after the entire block. – brhans Mar 21 '19 at 15:33
  • @brhans, I've come across the function but It only seems to be called by other HAL functions. I've not seen implemented in any user program yet. This tutorial also seems to use `ConvCpltCallback` – MaskedAfrican Mar 21 '19 at 16:56
  • 1
    That doesn't really answer my question or indicate that you've grasped my point. Do you not see that it's unsurprising that you're seeing a half-empty buffer, when the callback you're using occurs before the DMA operation is complete (since that callback is unrelated to the DMA)? Read up on the HAL library documentation and `HAL_DMA_RegisterCallback` in particular. – brhans Mar 21 '19 at 17:04
  • Old thread I know, but I tripped on this one... DMA_Complete :-() – ChrisR Apr 26 '23 at 07:44

0 Answers0