Skip to main content
AHakk.1
Associate III
May 29, 2023
Question

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

  • May 29, 2023
  • 2 replies
  • 1677 views

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);
 
}
 
 

This topic has been closed for replies.

2 replies

AHakk.1
AHakk.1Author
Associate III
May 29, 2023
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 III
May 29, 2023

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