cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WL ping-pong example ADC polling works but DMA is not

AHakk.1
Associate III

Hello everyone, I ve been trying to implement DMA ADC to ping-pong example for 5-6 days.

I made HAL_ADC_PollForConversion made without problem. When I try to implement dma + adc, it return 0.

I reviewed lorawan adc.c example for polling (there is no dma example).

https://github.com/STMicroelectronics/STM32CubeWL/blob/main/Projects/NUCLEO-WL55JC/Demonstrations/LocalNetwork/LocalNetwork_Sensor/Core/Src/adc.c

I added these on sys_app.c

static void Gpio_PreInit(void)
{
  /* USER CODE BEGIN Gpio_PreInit_1 */
 
  /* USER CODE END Gpio_PreInit_1 */
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* Configure all IOs in analog input              */
  /* Except PA143 and PA14 (SWCLK and SWD) for debug*/
  /* PA13 and PA14 are configured in debug_init     */
  /* Configure all GPIO as analog to reduce current consumption on non used IOs */
  /* Enable GPIOs clock */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
 
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  /* All GPIOs except debug pins (SWCLK and SWD) */
  GPIO_InitStruct.Pin = GPIO_PIN_All & (~(GPIO_PIN_13 | GPIO_PIN_14));
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /* All GPIOs */
  GPIO_InitStruct.Pin = GPIO_PIN_All;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
 
  /* Disable GPIOs clock */
  __HAL_RCC_GPIOA_CLK_DISABLE();
  __HAL_RCC_GPIOB_CLK_DISABLE();
  __HAL_RCC_GPIOC_CLK_DISABLE();
  __HAL_RCC_GPIOH_CLK_DISABLE();
  /* USER CODE BEGIN Gpio_PreInit_2 */
 
  /* USER CODE END Gpio_PreInit_2 */
}

 I add adc.c like this:

 
/* Includes ------------------------------------------------------------------*/
#include "adc.h"
 
ADC_HandleTypeDef hadc;
 
/* ADC init function */
void MX_ADC_Init(void)
{
 
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  hadc.Instance = ADC;
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc.Init.LowPowerAutoWait = DISABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  hadc.Init.ContinuousConvMode = ENABLE;
  hadc.Init.NbrOfConversion = 1;
  hadc.Init.DiscontinuousConvMode = DISABLE;
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc.Init.DMAContinuousRequests = ENABLE;
  hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_39CYCLES_5;
  hadc.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
  hadc.Init.OversamplingMode = DISABLE;
  hadc.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }
  /* Configure Regular Channel */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
 
}
 
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
 
  if(adcHandle->Instance==ADC)
  {
  /* USER CODE BEGIN ADC_MspInit 0 */
 
  /* USER CODE END ADC_MspInit 0 */
    /* ADC clock enable */
    __HAL_RCC_ADC_CLK_ENABLE();
  /* USER CODE BEGIN ADC_MspInit 1 */
 
  /* USER CODE END ADC_MspInit 1 */
  }
}
 
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
 
  if(adcHandle->Instance==ADC)
  {
  /* USER CODE BEGIN ADC_MspDeInit 0 */
 
  /* USER CODE END ADC_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC_CLK_DISABLE();
  /* USER CODE BEGIN ADC_MspDeInit 1 */
 
  /* USER CODE END ADC_MspDeInit 1 */
  }
}
 

In my ping-pong example, in subghz_phy_app.c I added this function:

void SubghzApp_Init(void)
{
  /* USER CODE BEGIN SubghzApp_Init_1 */
  MX_DMA_Init();
 
  MX_ADC_Init();
 
  ADXL345_Init();
.
.
.
}
 
static void ADC_ReadChannels(void)
{
  /* USER CODE BEGIN ADC_ReadChannels_1 */
 
  /* USER CODE END ADC_ReadChannels_1 */
 
  /* Start Calibration */
  //if (HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK)
  //{
  // Error_Handler();
  // }
 
  if (HAL_ADC_Start(&hadc) != HAL_OK)
  {
    /* Start Error */
    Error_Handler();
  }
  /** Wait for end of conversion */
  HAL_ADC_PollForConversion(&hadc, 1);
 
  /** Wait for end of conversion */
  HAL_ADC_Stop(&hadc) ;   /* it calls also ADC_Disable() */
 
  ADCxConvertedValues = HAL_ADC_GetValue(&hadc);
 
  /* USER CODE BEGIN ADC_ReadChannels_2 */
 
  /* USER CODE END ADC_ReadChannels_2 */
}

While doing these, when I call ADC_ReadChannels(); function in 10 ms timer, I can get ADC data with polling.

When I change ADC_ReadChannels like this:

void SubghzApp_Init(void)
{
  MX_DMA_Init();
 
  MX_ADC_Init();
 
  ADXL345_Init();
 
  ADC_ReadChannels();
}
 
static void ADC_ReadChannels(void)
{
  HAL_ADC_Start_DMA(&hadc, (uint32_t*) rxBuf, 8192);
}
 

 rxBuf returns 0. How can I get data with adc dma ? Can you please help, I couldn't find any example.

my dma settings on dma.c

#include "dma.h"
 
void MX_DMA_Init(void)
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMAMUX1_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
 
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
 
  /* DMA1_Channel5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
 
}
 
 

2 REPLIES 2
AHakk.1
Associate III
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
	callback_state = 1;
 
}
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	callback_state = 2;
 
}

callback_state doesnt't change always 0.

Danish1
Lead II

I seem to remember that by default the sequencer is set up to send the stm32 into a deep power-saving mode when there are no tasks to run. That power-saving mode turns off HS oscillator as well as stopping the processor - killing any DMA or TIMER activity you have set up.

I don’t remember the details but there is a #define to disable deep sleep.

Hope this helps,

Danish