cancel
Showing results for 
Search instead for 
Did you mean: 

ADC Trigger scan mode

Chuev.Vladimir
Associate III

I am using stm32h745i-disco.

I need to run ADC in ScanConvMode mode because I need the exact sampling frequency.

But my ADC constantly gets into HAL_ADC_ErrorCallback with code 2 (Overrun).

I noticed that the call frequency of HAL_ADC_ErrorCallback is several times lower than the timer frequency.

Also, if I turn on ADC_SOFTWARE_START then nothing happens at all.

uint16 adcConvertedValues[4] = {0};
 
void Run() {
	HAL_TIM_Base_Start_IT(&htim1);
 
	HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
 
	HAL_ADC_Start_DMA(&hadc3, (uint32*)&adcConvertedValues[0], 4);
}
void MX_ADC3_Init(void) {
	ADC_ChannelConfTypeDef sConfig = { 0 };
 
	hadc3.Instance = ADC3;
	hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
	hadc3.Init.Resolution = ADC_RESOLUTION_16B;
	hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
	hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
	hadc3.Init.LowPowerAutoWait = DISABLE;
	hadc3.Init.ContinuousConvMode = DISABLE;
	hadc3.Init.NbrOfConversion = 4;
	hadc3.Init.DiscontinuousConvMode = DISABLE;
	hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_TRGO;
	hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
	hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
	hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;
	hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
	hadc3.Init.OversamplingMode = DISABLE;
	if (HAL_ADC_Init(&hadc3) != HAL_OK) {
		CriticalError();
	}
 
	sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	sConfig.SingleDiff = ADC_SINGLE_ENDED;
	sConfig.OffsetNumber = ADC_OFFSET_NONE;
	sConfig.Offset = 0;
 
 
	/** Configure Regular Channel */
	sConfig.Channel = ADC_CHANNEL_0;
	sConfig.Rank = ADC_REGULAR_RANK_1;
	if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
		CriticalError();
	}
 
	/** Configure Regular Channel */
	sConfig.Channel = ADC_CHANNEL_1;
	sConfig.Rank = ADC_REGULAR_RANK_2;
	if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
		CriticalError();
	}
 
	/** Configure Regular Channel */
	sConfig.Channel = ADC_CHANNEL_7;
	sConfig.Rank = ADC_REGULAR_RANK_3;
	if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
		CriticalError();
	}
 
	/** Configure Regular Channel */
	sConfig.Channel = ADC_CHANNEL_10;
	sConfig.Rank = ADC_REGULAR_RANK_4;
	if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
		CriticalError();
	}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) {
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };
	if (hadc->Instance == ADC3) {
 
		__HAL_RCC_ADC3_CLK_ENABLE();
		__HAL_RCC_GPIOF_CLK_ENABLE();
		__HAL_RCC_GPIOC_CLK_ENABLE();
 
		GPIO_InitStruct.Pin = GPIO_PIN_8;
		GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
		GPIO_InitStruct.Pin = GPIO_PIN_0;
		GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
		HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, SYSCFG_SWITCH_PC2_OPEN);
		HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_OPEN);
 
		/* ADC3 DMA Init */
		hdma_adc3.Instance = DMA2_Stream0;
		hdma_adc3.Init.Request = DMA_REQUEST_ADC3;
		hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
		hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
		hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
		hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
		hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
		hdma_adc3.Init.Mode = DMA_CIRCULAR;
		hdma_adc3.Init.Priority = DMA_PRIORITY_MEDIUM;
		hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
		if (HAL_DMA_Init(&hdma_adc3) != HAL_OK) {
			CriticalError();
		}
 
		__HAL_LINKDMA(hadc, DMA_Handle, hdma_adc3);
 
		/* ADC3 interrupt Init */
		HAL_NVIC_SetPriority(ADC3_IRQn, 5, 0);
		HAL_NVIC_EnableIRQ(ADC3_IRQn);
	}
}

void MX_TIM1_Init(void) {
	TIM_MasterConfigTypeDef sMasterConfig = { 0 };
	TIM_OC_InitTypeDef sConfigOC = { 0 };
	TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = { 0 };
 
	htim1.Instance = TIM1;
	htim1.Init.Prescaler = (240 * 30) - 1;
	htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim1.Init.Period = 10000;
	htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	htim1.Init.RepetitionCounter = 0;
	htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	if (HAL_TIM_OC_Init(&htim1) != HAL_OK) {
		CriticalError();
	}
 
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
	sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
	if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) {
		CriticalError();
	}
 
	sConfigOC.OCMode = TIM_OCMODE_TIMING;
	sConfigOC.Pulse = htim1.Init.Period / 2;
	sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
	sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
	sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
	sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
	sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
	if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
		CriticalError();
	}
 
	sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
	sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
	sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
	sBreakDeadTimeConfig.DeadTime = 0;
	sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
	sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
	sBreakDeadTimeConfig.BreakFilter = 0;
	sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
	sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
	sBreakDeadTimeConfig.Break2Filter = 0;
	sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
	if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) {
		CriticalError();
	}
}

2 REPLIES 2
TDK
Guru

> sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;

Increase this time so that your DMA has time to move stuff before the next conversion completes. Using the FIFO might also alleviate this problem.

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

1) I set ADC_CLOCK_ASYNC_DIV256 and ADC_SAMPLETIME_810CYCLES_5 but still got error 2.

2) After that, I removed the Trig by timer and just did ContinuousConvMode, but nothing changed

3) I noticed that my DMA interrupt is not called at all.

3.1) Inside DMA1_Stream3_IRQHandler there was also no HAL_DMA_IRQHandler, the cube simply does not generate it. I added it manually

3.2) I checked that I have an interrupt enabled inside my MX_DMA_Init.

I have no idea what to do my ADC just doesn't work