2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – brhans Mar 21 at 15:33
  • \$\begingroup\$ @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 \$\endgroup\$ – MaskedAfrican Mar 21 at 16:56
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – brhans Mar 21 at 17:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.