Skip to main content
reedomneck
Associate III
Jun 4, 2025 8:36 AM UTC
Solved

ADC read in DMA regular mode

I've requirement of reading 100 samples of ADC data using DMA whenever it's needed in regular mode and I see the read buffer is not having right values and also HAL_ADC_ConvCpltCallback is not hitting.
But same if I try just with one sample data is proper and HAL_ADC_ConvCpltCallback is hitting but when I retrigger ADC_DMA_READ I see HAL_BUSY.
I'm using NUCLEO-545REQ board
 
/*GLOBAL VARIABLE*/
#define ADC_CONVERTED_DATA_BUFFER_SIZE ((uint32_t) 100) /* Size of array aADCxConvertedData[] */
/* Variable containing ADC conversions data */
uint32_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];
int isADCFinished = 0;
#define VDDA_APPLI (3300UL)
uint16_t uhADCxConvertedData_Voltage_mVolt = 0; /* Value of voltage calculated from ADC conversion data (unit: mV) */
/* Init variable out of expected ADC conversion data range */
#define VAR_CONVERTED_DATA_INIT_VALUE (__LL_ADC_DIGITAL_SCALE(ADC1, LL_ADC_RESOLUTION_14B) + 1)
/*************************************************************************************************/

int main(void)
{
 /* USER CODE BEGIN 1 */
 /* USER CODE END 1 */

 /* 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 Power */
 SystemPower_Config();

 /* Configure the system clock */
 SystemClock_Config();

 /* USER CODE BEGIN SysInit */
 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_GPDMA1_Init();
 MX_ADC1_Init();
 MX_ICACHE_Init();
 /* USER CODE BEGIN 2 */
 /* USER CODE END 2 */

 /* Initialize led */
 BSP_LED_Init(LED_GREEN);

 /* 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();
 }
 if (HAL_ADC_Start_DMA(&hadc1,
 (uint32_t *)aADCxConvertedData,
 (ADC_CONVERTED_DATA_BUFFER_SIZE)
 ) != HAL_OK)
 {
 Error_Handler();
 }
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 if(isADCFinished == 1)
 {
 isADCFinished = 0;
 uhADCxConvertedData_Voltage_mVolt = __LL_ADC_CALC_DATA_TO_VOLTAGE(ADC1, VDDA_APPLI, aADCxConvertedData[0], LL_ADC_RESOLUTION_14B);
 if (HAL_ADC_Start_DMA(&hadc1,
 (uint32_t *)aADCxConvertedData,
 (ADC_CONVERTED_DATA_BUFFER_SIZE)
 ) != HAL_OK)
 {

 Error_Handler();
 }
 }

 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
 isADCFinished = 1;
}

static void MX_ADC1_Init(void)
{
 /* USER CODE BEGIN ADC1_Init 0 */
 /* USER CODE END ADC1_Init 0 */

 ADC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN ADC1_Init 1 */

 /* USER CODE END ADC1_Init 1 */

 /** Common config
 */
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc1.Init.Resolution = ADC_RESOLUTION_14B;
 hadc1.Init.GainCompensation = 0;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = DISABLE;
 hadc1.Init.ContinuousConvMode = ENABLE;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
 hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
 hadc1.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_1;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_5CYCLE;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC1_Init 2 */

 /* USER CODE END ADC1_Init 2 */

}

/**
 * @brief GPDMA1 Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_GPDMA1_Init(void)
{

 /* USER CODE BEGIN GPDMA1_Init 0 */

 /* USER CODE END GPDMA1_Init 0 */

 /* Peripheral clock enable */
 __HAL_RCC_GPDMA1_CLK_ENABLE();

 /* GPDMA1 interrupt Init */
 HAL_NVIC_SetPriority(GPDMA1_Channel15_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(GPDMA1_Channel15_IRQn);

 /* USER CODE BEGIN GPDMA1_Init 1 */

 /* USER CODE END GPDMA1_Init 1 */
 /* USER CODE BEGIN GPDMA1_Init 2 */

 /* USER CODE END GPDMA1_Init 2 */

}

Edited to apply source code formatting - please see How to insert source code for future reference.

This topic has been closed for replies.
TDK
TDKBest answer
Jun 4, 2025 12:28 PM UTC

If resolution is 14 bits, the buffer data type should be uint16_t and the dma word size should be half-word.

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

3 replies

reedomneck
Associate III
Jun 4, 2025 9:05 AM UTC

This data not proper problem I've fixed. Now I've problem in reading 100 samples, I don't knwo why maximum 32 samples it's able to read

TDK
TDKBest answer
Jun 4, 2025 12:28 PM UTC

If resolution is 14 bits, the buffer data type should be uint16_t and the dma word size should be half-word.

"If you feel a post has answered your question, please click ""Accept as Solution""."
reedomneck
Associate III
Jun 4, 2025 4:01 PM UTC

@TDK  Thanks for your reply I'm able to get it working