Skip to main content
Marius CO
Associate II
May 22, 2019
Question

ADC3 on STM303F3xx not working (PB0, PB1).

  • May 22, 2019
  • 0 replies
  • 448 views

I have an old project already using PA 0,1,2,3,5,7 and PC 1,2,3 as analogue inputs, all on ADC 1 and 2. Due the nature of the project I read some of them in a interrupt timer, and some on demand,when a UART command kicks in.

I had to add 3 more ADC's on PB0 PB1 PB2 on ADC3. My code follows same initialization for ADC3 as ADC1/2, which is standard CUBEMX code.

Upon reading, the ADC3 times out waiting for ISR bit.

static HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef* hadc)
{
 uint32_t tickstart = 0U;
 
 /* ADC enable and wait for ADC ready (in case of ADC is disabled or */
 /* enabling phase not yet completed: flag ADC ready not yet set). */
 /* Timeout implemented to not be stuck if ADC cannot be enabled (possible */
 /* causes: ADC clock not running, ...). */
 if (ADC_IS_ENABLE(hadc) == RESET)
 {
 /* Check if conditions to enable the ADC are fulfilled */
 if (ADC_ENABLING_CONDITIONS(hadc) == RESET)
 {
 /* Update ADC state machine to error */
 SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
 
 /* Set ADC error code to ADC IP internal error */
 SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
 
 return HAL_ERROR;
 }
 
 /* Enable the ADC peripheral */
 __HAL_ADC_ENABLE(hadc);
 
 /* Wait for ADC effectively enabled */
 tickstart = HAL_GetTick(); 
 
 while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == RESET)
 {
 if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
 {
 /* Update ADC state machine to error */
 SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
 
 /* Set ADC error code to ADC IP internal error */
 SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
 
 return HAL_ERROR; <<<<==== TIMEOUTS
 }
 }
 }
 
 /* Return HAL status */
 return HAL_OK;
}

I disabled all the code around leaving only the ADC3. The flags and timer for ADC3 is started. I am struggling with this issue for a 2 days now. Here is my code for reference. Anyone can spot something wrong would be appreciated.

My Init code (never failed on ADC1 and 2 for few months)

///////////////////////////////////////////
// MAIN
{
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_USART3_UART_Init();
	INIT_PWM_TIMERS() // TIM2(10Khz) TIM3-ch1,ch2 (100Khz) TIM4-ch1,2,3,4 (100Khz) & __HAL_RCC_TIM 2,3,4_CLK_ENABLE
//	MX_ADC1_Init();
//	MX_ADC2_Init();
	MX_ADC3_Init();
//	readPinValue(PA7); //<- this works on ADC2
	readPinValue(PB0); //<- this fails
	return 0;
}
 
/////////////////////////////////////////////////////////////
MX_ADC[1..3]_Init()
{
 ADC_ChannelConfTypeDef sConfig;
 
 hadc3.Instance = ADC[1..3];
 myInit_Adc(&hadc[1..3]);
 if (HAL_ADC_Init(&hadc[1..3]) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 myInitChannels(&hadc[1..3], &sConfig);
}
 
/////////////////////////////////////////////////////////////
static void myInit_Adc(ADC_HandleTypeDef* hadc)
{
 hadc->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc->Init.Resolution = ADC_RESOLUTION_12B;
 hadc->Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc->Init.ScanConvMode = ADC_SCAN_DISABLE;
 hadc->Init.EOCSelection = DISABLE; // to turn on once. ADC_EOC_SINGLE_CONV; //ADC_EOC_SEQ_CONV
 hadc->Init.LowPowerAutoWait = DISABLE;
 //hadc->Init.LowPowerAutoPowerOff = DISABLE;
 hadc->Init.ContinuousConvMode = DISABLE;
 hadc->Init.DiscontinuousConvMode = DISABLE;
 hadc->Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc->Init.DMAContinuousRequests = DISABLE;
 hadc->Init.Overrun = ADC_OVR_DATA_PRESERVED;
}
 
/////////////////////////////////////////////////////////////
static void myInitChannels(ADC_HandleTypeDef* hadc,
 ADC_ChannelConfTypeDef* sConfig)
{
 struct AnalogPin* pp = &Anals[0];
 for(; pp->typ!=PNA; pp++)
 {
 if(pp->adc == hadc)
 {
 sConfig->Channel = pp->channel; // from PIN right channel
 sConfig->Rank = pp->rank;	 // allways ADC_RANK_CHANNEL_NUMBER
 sConfig->SingleDiff = ADC_SINGLE_ENDED;
 sConfig->SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
 sConfig->OffsetNumber = ADC_OFFSET_NONE;
 sConfig->Offset = 0;
 if (HAL_ADC_ConfigChannel(hadc, sConfig) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 }
 }
}

///
/// MSP INIT
///
 
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct;
 if(adcHandle->Instance==ADC1)
 {
 HAL_RCC_ADC12_CLK_ENABLED++;
 if(HAL_RCC_ADC12_CLK_ENABLED==1){
 __HAL_RCC_ADC12_CLK_ENABLE();
 }
 
 /**ADC1 GPIO Configuration
 PC0 ------> ADC1_IN6
 PC1 ------> ADC1_IN7
 PC2 ------> ADC1_IN8
 PC3 ------> ADC1_IN9
 PA0 ------> ADC1_IN1
 PA1 ------> ADC1_IN2
 PA2 ------> ADC1_IN3
 PA3 ------> ADC1_IN4
 */
 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 }
 else if(adcHandle->Instance==ADC2)
 {
 HAL_RCC_ADC12_CLK_ENABLED++;
 if(HAL_RCC_ADC12_CLK_ENABLED==1){
 __HAL_RCC_ADC12_CLK_ENABLE();
 }
 
 /**ADC2 GPIO Configuration
 PA5 ------> ADC2_IN2
 PA6 ------> ADC2_IN3
 PA7 ------> ADC2_IN4
 PB2 ------> ADC2_IN12
 */
 GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 }
 else if(adcHandle->Instance==ADC3)
 {
 /* USER CODE BEGIN ADC3_MspInit 0 */
 HAL_RCC_ADC34_CLK_ENABLED++;
 if(HAL_RCC_ADC34_CLK_ENABLED==1){
 __HAL_RCC_ADC34_CLK_ENABLE();
 }
 /**ADC3 GPIO Configuration
 PB0 ------> ADC3_IN12
 PB1 ------> ADC3_IN1
 */
 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 }
}

My read code:

 
 //
 // SELECT ADC
 //
 ADC_ChannelConfTypeDef sConfig;
 sConfig.Channel = ADC_CHANNEL_[FOR PIN]; (11 for ADC3 PB0)
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 HAL_ADC_ConfigChannel(HADC, &sConfig);
	//
	// START
	//
	HAL_ADC_Start(HADC); /// <<<< fails for ADC3 as described above
	//
	// rewad
	//
	HAL_ADC_PollForConversion(...)
	HAL_ADC_GetValue(...)
	HAL_ADC_Stop(HADC);

This topic has been closed for replies.