Skip to main content
Saif
Associate II
April 20, 2023
Question

The DMA transfer only the first byte from ADC1 (STM32H735)

  • April 20, 2023
  • 10 replies
  • 3772 views

I configure the ADC1 of the STM32H735 like bellow:

The ADC Clock = 20MHz

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
 
/* ADC1 init function */
void MX_ADC1_Init(void)
{
 
 /* USER CODE BEGIN ADC1_Init 0 */
 
 /* USER CODE END ADC1_Init 0 */
 
 ADC_MultiModeTypeDef multimode = {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_DIV4;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = 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.NbrOfDiscConversion = 1;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
 hadc1.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 sConfig.OffsetSignedSaturation = DISABLE;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC1_Init 2 */
 
 /* USER CODE END ADC1_Init 2 */
 
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
 
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 if(adcHandle->Instance==ADC1)
 {
 /* USER CODE BEGIN ADC1_MspInit 0 */
 
 /* USER CODE END ADC1_MspInit 0 */
 
 /** Initializes the peripherals clock
 */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
 PeriphClkInitStruct.PLL3.PLL3M = 2;
 PeriphClkInitStruct.PLL3.PLL3N = 40;
 PeriphClkInitStruct.PLL3.PLL3P = 2;
 PeriphClkInitStruct.PLL3.PLL3Q = 5;
 PeriphClkInitStruct.PLL3.PLL3R = 25;
 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_3;
 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
 PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL3;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* ADC1 clock enable */
 __HAL_RCC_ADC12_CLK_ENABLE();
 
 __HAL_RCC_GPIOA_CLK_ENABLE();
 /**ADC1 GPIO Configuration
 PA0_C ------> ADC1_INP0
 */
 HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PA0, SYSCFG_SWITCH_PA0_OPEN);
 
 /* ADC1 DMA Init */
 /* ADC1 Init */
 hdma_adc1.Instance = DMA1_Stream1;
 hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
 hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
 hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_adc1.Init.Mode = DMA_CIRCULAR;
 hdma_adc1.Init.Priority = DMA_PRIORITY_MEDIUM;
 hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);
 
 /* USER CODE BEGIN ADC1_MspInit 1 */
 
 /* USER CODE END ADC1_MspInit 1 */
 }
}

The ADC1_DR register = 0xFFE (I put 3.3V in PA0_C pin) it is ok.


_legacyfs_online_stmicro_images_0693W00000biUC8QAM.pngbut in the buffer, the dma transfer only the first byte :


_legacyfs_online_stmicro_images_0693W00000biUKvQAM.pngI did not understand why the DMA always transfers a Byte despite I made several configuration combinations.

Best Regards,

This topic has been closed for replies.

10 replies

LCE
Principal II
April 20, 2023

Please show us the buffer declaration and how you start DMA.

Saif
SaifAuthor
Associate II
April 20, 2023
extern ADC_HandleTypeDef hadc1;
ALIGN_32BYTES (static uint16_t aADCxConvertedData[4]);
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
static void CPU_CACHE_Enable(void);
/* 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 ---------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
/**
 * @brief The application entry point.
 * @retval int
 */
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 clock */
 SystemClock_Config();
 
 /* USER CODE BEGIN SysInit */
 
 /* USER CODE END SysInit */
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_ADC1_Init();
 MX_DMA_Init();
 /* USER CODE BEGIN 2 */
 HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)aADCxConvertedData, 4 );
 
 /* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */
 
 }
 /* USER CODE END 3 */
}

LCE
Principal II
April 20, 2023

Looks exactly like my working H7 ADC code.

LCE
Principal II
April 20, 2023

And you could try:

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

Saif
SaifAuthor
Associate II
April 20, 2023

Same problem

LCE
Principal II
April 20, 2023

I'm using ADC3 on a H723 / H735.

I don't see any GPIO init, is that included in HAL_SYSCFG_AnalogSwitchConfig() ?

There's this line in my init concerning ADC data alignment in the data register:

hAdc3.Init.DataAlign = ADC3_DATAALIGN_RIGHT;

Here's my working HAL setup, but I use multiple channels.

uint8_t ADC3_InitStartDma(void)
{
	/* Configure the global features of the ADC:
	 * Clock, Resolution, Data Alignment and number of conversion
	 */
	hAdc3.Instance = ADC3;
 
	hAdc3.Init.ClockPrescaler 			= ADC_CLOCK_ASYNC_DIV32;
	hAdc3.Init.Resolution 				= ADC_RESOLUTION_12B;
	hAdc3.Init.DataAlign 				= ADC3_DATAALIGN_RIGHT;
	hAdc3.Init.ScanConvMode 			= ADC_SCAN_ENABLE;
	hAdc3.Init.ContinuousConvMode 		= ENABLE;
	hAdc3.Init.EOCSelection 			= ADC_EOC_SEQ_CONV;
	hAdc3.Init.LowPowerAutoWait 		= DISABLE;
	hAdc3.Init.NbrOfConversion 			= ADC_CHNL_MAX;
	hAdc3.Init.DiscontinuousConvMode 	= DISABLE;
	hAdc3.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;
	hAdc3.Init.ExternalTrigConvEdge 	= ADC_EXTERNALTRIGCONVEDGE_NONE;
	hAdc3.Init.DMAContinuousRequests 	= ENABLE;
	hAdc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
	hAdc3.Init.SamplingMode 			= ADC_SAMPLING_MODE_NORMAL;
	hAdc3.Init.Overrun 					= ADC_OVR_DATA_OVERWRITTEN;
	//hAdc3.Init.Overrun 					= ADC_OVR_DATA_PRESERVED;
	hAdc3.Init.LeftBitShift 			= ADC_LEFTBITSHIFT_NONE;
	hAdc3.Init.OversamplingMode 		= DISABLE;
 
	if( HAL_ADC_Init(&hAdc3) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);
 
	/* self calibration */
	if( HAL_ADCEx_Calibration_Start(&hAdc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED ) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);
 
	return HAL_ADC_Start_DMA(&hAdc3, (uint32_t *)u16Adc3DmaBuffer, ADC_DMA_BUF_SIZE);
}

LCE
Principal II
April 20, 2023

Man, that's ugly source code with my tab settings, sorry... :grinning_face_with_sweat:

LCE
Principal II
April 20, 2023

@Saif​ Have you enabled the DMA interrupts somewhere?

/* ADC DMA interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0);

HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

SA V.1
Associate III
April 21, 2023

Hello sir , My Dout is

1*.  We must and should Enable the Bellow interrupt to Collect ADC Data ??

( In H7XX series and CubeIDE )

/* DMA interrupt init */

 /* DMA1_Stream0_IRQn interrupt configuration */

 HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);

 HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

2*. If we Disable the the DMA interrupt is it possible Recieve ADC data or Not ??

Please can you Clear this Dout

Thank You ,

Best Regards

Sharath A V

Senior III
April 21, 2023
  1. Try change hadc1.Init.LowPowerAutoWait = DISABLE to ENABLE

Dudo
SA V.1
Associate III
April 21, 2023

Where is your Callback Function ?? if your not wrote in your code write callback function in User code 4 and Check .

/* USER CODE BEGIN 4 */

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)

{

for(int i=0; i<=4; i++)

{

  aADCxConvertedData[i] = HAL_ADC_GetValue(&hadc1);

}

}

Senior III
April 21, 2023

@SA V.1​ Your code is ok as debug, but when use DMA we consciously avoid calling HAL_ADC_Get_Value. if use HAL_ADC_Start_DMA(&hadc1,(uint32_t*)aADCxConvertedData, 4 ) the function automatically fill aADCxConvertedData.

I have simillar problem far time ago and Enabling "lowPowerAutopWait" helped me

Dudo
SA V.1
Associate III
April 21, 2023

Yes, Your right but to simply check weather data is getting or not so that's why i said above function . And what you will write inside the Callback function ?? in my code i wrote

SCB_InvalidateDCache_by_Addr((uint32_t *) &ADC_Data[0], BUFFER_SIZE); can you share what you write ?? everything fine but my big Dout is DMA interrupt still i didnt get any clarity . i tried many without DMA interrupt not get any data .

Thank you for your support

best regards

Sharath A V

Senior III
April 21, 2023

You don't need callback function to receive data through DMA.

It's OPTIONAL. Please read reference manual deeper

Dudo
LCE
Principal II
April 24, 2023

@Saif​ Did you have any success?

Saif
SaifAuthor
Associate II
April 25, 2023

Hi all

I don't know what I'm going to say, but maybe you don't believe me.

I put back the same configuration that I wrote in my question, and the ADC works correctly now despite there being no change.

Apparently, I will spend some time reproducing the problem to understand.

Best Regards,

LCE
Principal II
April 25, 2023

Nice that it's working now!

Are you sure that you didn't change stuff elsewhere, like:

  • clock settings
  • DMA interrupts

Oh, I just see the old CubeMX problem, putting DMA init after peripheral init using DMA.

In your 2nd source code post it is:

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_ADC1_Init();

MX_DMA_Init(); <<<< this must be before any peripheral using DMA!

I guess you changed your main, maybe by updating CubeMX?

Known bug, and it bugs me that I haven't seen that earlier! ;)