cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F04 ADC multiple channel DMA single shot mode problem

jiangpen
Associate II
Posted on May 10, 2018 at 08:02

Hi ALL,

I develop an application based on STM32F04. There are 3 ADC channels and I used DMA to collect data from these 3 channels.

It can get correct data from ADC, but there is a problem.

If I call the HAL_ADC_Start_DMA  before main loop to trigger DMA  convert, the HAL_ADC_ConvCpltCallback does not get called. If I call HAL_ADC_Start_DMA in my main loop in every 1 second, the HAL_ADC_ConvCpltCallback takes age to be called (3-4 second later).

If I configure the ADC as continual and DMA as circular mode, then it is OK, I can see the HAL_ADC_ConvCpltCallback get called very often. But I really cannot use this mode for my application.

Many thanks

The ADC configure is:

static __IO uint16_t aADCxConvertedData[3*8];

//below code is used to collect data from 3 ADC channel, and take average of 8 to reduce the noise.

HAL_ADC_Start_DMA( &hadc, (uint32_t *)aADCxConvertedData, 3*8);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  hadc.Instance = ADC1;

  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

  hadc.Init.Resolution = ADC_RESOLUTION_12B;

  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

  hadc.Init.LowPowerAutoWait = ENABLE;

  hadc.Init.LowPowerAutoPowerOff = ENABLE;

  hadc.Init.ContinuousConvMode = DISABLE;

  hadc.Init.DiscontinuousConvMode = DISABLE;

  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

  hadc.Init.DMAContinuousRequests = DISABLE;

  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;

  if (HAL_ADC_Init(&hadc) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

    /**Configure for the selected ADC regular channel to be converted.

    */

  sConfig.Channel = ADC_CHANNEL_1;

  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

  sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;

  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

    /**Configure for the selected ADC regular channel to be converted.

    */

  sConfig.Channel = ADC_CHANNEL_5;

  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

    /**Configure for the selected ADC regular channel to be converted.

    */

  sConfig.Channel = ADC_CHANNEL_6;

  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

DMA configures as :

   hdma_adc.Instance = DMA1_Channel1;

    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;

    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_adc.Init.MemInc = DMA_MINC_ENABLE;

    hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

    hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

    hdma_adc.Init.Mode = DMA_NORMAL;

    hdma_adc.Init.Priority = DMA_PRIORITY_LOW;

My interrupt handler is:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)

{

    if (__HAL_ADC_GET_FLAG(AdcHandle, ADC_FLAG_EOS))

    {

        //do read the ADC data here

    }

}

The system clock is configured as blow: HSI14 should be used for ADC.

void SystemClock_Config(void)

{

  RCC_OscInitTypeDef RCC_OscInitStruct;

  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks

    */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSI48

                              |RCC_OSCILLATORTYPE_LSI;

  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;

  RCC_OscInitStruct.HSI14State = RCC_HSI14_ON;

  RCC_OscInitStruct.HSI14CalibrationValue = 16;

  RCC_OscInitStruct.LSIState = RCC_LSI_ON;

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

    /**Initializes the CPU, AHB and APB busses clocks

    */

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

                              |RCC_CLOCKTYPE_PCLK1;

  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48;

  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB|RCC_PERIPHCLK_USART1

                              |RCC_PERIPHCLK_RTC;

  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;

  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;

  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

    /**Configure the Systick interrupt time

    */

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick

    */

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */

  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}
0 REPLIES 0