Skip to main content
Visitor II
June 4, 2025
Solved

ADC read in DMA regular mode

  • June 4, 2025
  • 3 replies
  • 448 views
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.
    Best answer by TDK

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

    3 replies

    Visitor II
    June 4, 2025

    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

    TDKAnswer
    Super User
    June 4, 2025

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

    Visitor II
    June 4, 2025

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