cancel
Showing results for 
Search instead for 
Did you mean: 

cubeide NucleoH723ZG ADC callback not working with DMA

DG91
Associate

Hello,

I am trying to read from ADC with DMA using HAL_ADC_Start_DMA.
Only with ADC I can read and printf the values. But once I configure DMA it seems that callback isn't working.

I am attaching the main.c as well as the whole project zipped. Is there anything else needed or any other way to utilize DMA for ADC? Would there be a possiibility that the library for HAL_ADC_ConvCpltCallback() not be working?


Please, any suggestions would be really appreciated. Thank you

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "dma.h" #include "i2c.h" #include "memorymap.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ COM_InitTypeDef BspCOMInit; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MPU_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ #define ADC_BUFFER_SIZE 1 uint32_t adc_value = 0; void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { if (hadc->Instance == ADC1) { // Print ADC value via UART BSP_LED_Toggle(LED3); printf("ADC Value: %d\r\n", (int)adc_value); // Restart ADC for next conversion HAL_ADC_Start_DMA(&hadc1, &adc_value, ADC_BUFFER_SIZE); } } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MPU Configuration--------------------------------------------------------*/ MPU_Config(); /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_ADC1_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Initialize leds */ BSP_LED_Init(LED_GREEN); BSP_LED_Init(LED_YELLOW); BSP_LED_Init(LED_RED); /* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/ BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); /* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */ BspCOMInit.BaudRate = 115200; BspCOMInit.WordLength = COM_WORDLENGTH_8B; BspCOMInit.StopBits = COM_STOPBITS_1; BspCOMInit.Parity = COM_PARITY_NONE; BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE; if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE) { Error_Handler(); } /* Infinite loop */ /* USER CODE BEGIN WHILE */ printf("Hello\r\n"); HAL_ADC_Start_DMA(&hadc1, &adc_value, ADC_BUFFER_SIZE); while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //BSP_LED_Toggle(LED3); HAL_Delay(100); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Supply configuration update enable */ HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); /** Configure the main internal regulator output voltage */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {} /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_DIV1; RCC_OscInitStruct.HSICalibrationValue = 64; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 4; RCC_OscInitStruct.PLL.PLLN = 34; RCC_OscInitStruct.PLL.PLLP = 1; RCC_OscInitStruct.PLL.PLLQ = 4; RCC_OscInitStruct.PLL.PLLR = 2; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; RCC_OscInitStruct.PLL.PLLFRACN = 3072; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /* MPU Configuration */ void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct = {0}; /* Disables the MPU */ HAL_MPU_Disable(); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.BaseAddress = 0x0; MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; MPU_InitStruct.SubRegionDisable = 0x87; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enables the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @PAram file: pointer to the source file name * @PAram line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */
View more

 

4 REPLIES 4
AScha.3
Super User

Hi,

you have callback enabled in Cube?

-->

AScha3_0-1740400393448.png

 

If you feel a post has answered your question, please click "Accept as Solution".

Dear @AScha.3 
thank you for your reply, yes it is activated.

I am attaching a respective screenshot.

DG91_0-1740401563190.png

Any suggestions would be really helpful. Thank you

Ok,

and how/where you start the ADC ?

I see only DMA is started.

 

btw

Can you explain, whats the sense of using the DMA, to just transfer one value ?

If you feel a post has answered your question, please click "Accept as Solution".
Saket_Om
ST Employee

Hello @DG91 

Please refer to the example  Projects/NUCLEO-H743ZI/Examples/ADC/ADC_DMA_Transfer in the STM32Cube firmware h7.

To read analogue input and get the result by DMA, these steps are required:

  • De-Initialize ADC peripheral
  • Initialize ADC peripheral
  • Start calibration
  • Channel configuration
  • Start conversion in DMA mode

Please look to the snippet code below: 

 

/* ### - 1 - Initialize ADC peripheral #################################### */ AdcHandle.Instance = ADCx; if (HAL_ADC_DeInit(&AdcHandle) != HAL_OK) { /* ADC de-initialization Error */ Error_Handler(); } AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; /* Asynchronous clock mode, input ADC clock divided by 2*/ AdcHandle.Init.Resolution = ADC_RESOLUTION_16B; /* 16-bit resolution for converted data */ AdcHandle.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */ AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* EOC flag picked-up to indicate conversion end */ AdcHandle.Init.LowPowerAutoWait = DISABLE; /* Auto-delayed conversion feature disabled */ AdcHandle.Init.ContinuousConvMode = ENABLE; /* Continuous mode enabled (automatic conversion restart after each conversion) */ AdcHandle.Init.NbrOfConversion = 1; /* Parameter discarded because sequencer is disabled */ AdcHandle.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */ AdcHandle.Init.NbrOfDiscConversion = 1; /* Parameter discarded because sequencer is disabled */ AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* Software start to trig the 1st conversion manually, without external event */ AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */ AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; /* ADC DMA circular requested */ AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; /* DR register is overwritten with the last conversion result in case of overrun */ AdcHandle.Init.OversamplingMode = DISABLE; /* No oversampling */ /* Initialize ADC peripheral according to the passed parameters */ if (HAL_ADC_Init(&AdcHandle) != HAL_OK) { Error_Handler(); } /* ### - 2 - Start calibration ############################################ */ if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK) { Error_Handler(); } /* ### - 3 - Channel configuration ######################################## */ sConfig.Channel = ADCx_CHANNEL; /* Sampled channel number */ sConfig.Rank = ADC_REGULAR_RANK_1; /* Rank of sampled channel number ADCx_CHANNEL */ sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; /* Sampling time (number of clock cycles unit) */ sConfig.SingleDiff = ADC_SINGLE_ENDED; /* Single-ended input channel */ sConfig.OffsetNumber = ADC_OFFSET_NONE; /* No offset subtraction */ sConfig.Offset = 0; /* Parameter discarded because offset correction is disabled */ if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK) { Error_Handler(); } /* ### - 4 - Start conversion in DMA mode ################################# */ if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE ) != HAL_OK) { Error_Handler(); }
View more

 

  

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om