cancel
Showing results for 
Search instead for 
Did you mean: 

ADC Error : only returns '0X01AF'

KenLee
Associate III

I'm using stm32c011f4u6 and keil5. and I'm using 2 ADC channels by Polling.

Every time I read an ADC channel, it only return '0X01AF'. This is the same for both channels,
even if I remove one channel and read it again with only one channel used, the same problem appears.

 

static void ADC_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  //!!! HAL_ADC_Init is commented because some parameters are missing
  hadc.Instance = ADC1;
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc.Init.LowPowerAutoWait = DISABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  hadc.Init.ContinuousConvMode = DISABLE;
  hadc.Init.NbrOfConversion = 1;
  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;
  hadc.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
  hadc.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;
  hadc.Init.OversamplingMode = DISABLE;
  hadc.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
	if(HAL_ADC_Init(&hadc) != HAL_OK)
	{
		Error_Handler();
	}	
	while(HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK);
}
uint16_t NTC1_Read(void)
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
	
	ADC_ChannelConfTypeDef sConfig = {0};
	
	sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
	{
		Error_Handler();
	}
	
	sConfig.Channel = ADC_CHANNEL_2;
	sConfig.Rank = ADC_RANK_NONE;
	sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
	{
		Error_Handler();
	}	
	
	HAL_ADC_Start(&hadc);
	HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
	ADC_CH1 = HAL_ADC_GetValue(&hadc);
	HAL_ADC_Stop(&hadc);
	
	CH1 = 3000 * ADC_CH1 / 4096; 
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
	
	return CH1;
}

uint16_t NTC2_Read(void)
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_SET);
	
	ADC_ChannelConfTypeDef sConfig = {0};
	
	sConfig.Channel = ADC_CHANNEL_1;
	sConfig.Rank = ADC_RANK_NONE;
	sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
	{
		Error_Handler();
	}	
	
	sConfig.Channel = ADC_CHANNEL_2;
	sConfig.Rank = 1;
	sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	if(HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
	{
		Error_Handler();
	}	
	
	HAL_ADC_Start(&hadc);
	HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
	ADC_CH2 = HAL_ADC_GetValue(&hadc);
	HAL_ADC_Stop(&hadc);
	
	CH2 = 3000 * ADC_CH2 / 4096;
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_RESET);
	
	return CH2;
}

 

 

These are my ADC functions. What's wrong with this program?

7 REPLIES 7
RomainR.
ST Employee

Hello @KenLee 

In ADC_Init() you're configuring ADC Scan mode for ADC_CHANNEL_1 and ADC_CHANNEL_2, you must also configure the correct number of conversion: 

hadc.Init.NbrOfConversion = 2;

Then, you must iterate the ADC conversion polling according the number of channel.

I recommend you to use ADC Scan mode and DMA to transfer directly each conversion in SRAM memory.

I suggest you to refer to STM32CubeC0 example:

https://github.com/STMicroelectronics/STM32CubeC0/tree/main/Projects/NUCLEO-C031C6/Examples/ADC/ADC_MultiChannelSingleConversion

I hope it will helps?

Best regards,

Romain   

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

 

I've tried changing the settings, but no matter how I call ADC_Start twice with NumberOfConversion as 1, or call once with 2, only 0x01af is output. Why is this happening?

Any error returned by HAL_ADC_Start() or HAL_ADC_PollForConversion()?

JW

When I checked, ADC_PollForConversion encountered an error. I marked the location of the error in red.

However, what I wonder is that when I created a new file and compiled it using the same settings and code, it worked fine. i really don't know why..

 

 

HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
{
uint32_t tickstart;
uint32_t tmp_Flag_End;

/* Check the parameters */
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));

/* If end of conversion selected to end of sequence conversions */
if (hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV)
{
tmp_Flag_End = ADC_FLAG_EOS;
}
/* If end of conversion selected to end of unitary conversion */
else /* ADC_EOC_SINGLE_CONV */
{
/* Verification that ADC configuration is compliant with polling for */
/* each conversion: */
/* Particular case is ADC configured in DMA mode and ADC sequencer with */
/* several ranks and polling for end of each conversion. */
/* For code simplicity sake, this particular case is generalized to */
/* ADC configured in DMA mode and and polling for end of each conversion. */
if ((hadc->Instance->CFGR1 & ADC_CFGR1_DMAEN) != 0UL)
{
/* Update ADC state machine to error */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);

return HAL_ERROR;
}
else
{
tmp_Flag_End = (ADC_FLAG_EOC);
}
}

/* Get tick count */
tickstart = HAL_GetTick();

/* Wait until End of unitary conversion or sequence conversions flag is raised */
while ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
{
/* Check if timeout is disabled (set to infinite wait) */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
{
/* Update ADC state machine to timeout */
SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);

/* Process unlocked */
__HAL_UNLOCK(hadc);

return HAL_TIMEOUT;
}
}
}

/* Update ADC state machine */
SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);

/* Determine whether any further conversion upcoming on group regular */
/* by external trigger, continuous mode or scan sequence on going. */
if ((LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
&& (hadc->Init.ContinuousConvMode == DISABLE)
)
{
/* Check whether end of sequence is reached */
if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS))
{
/* Allowed to modify bits ADC_IT_EOC/ADC_IT_EOS only if bit */
/* ADSTART==0 (no conversion on going) */
if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
{
/* Disable ADC end of single conversion interrupt on group regular */
/* Note: Overrun interrupt was enabled with EOC interrupt in */
/* HAL_Start_IT(), but is not disabled here because can be used */
/* by overrun IRQ process below. */
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC | ADC_IT_EOS);

/* Set ADC state */
ADC_STATE_CLR_SET(hadc->State,
HAL_ADC_STATE_REG_BUSY,
HAL_ADC_STATE_READY);
}
else
{
/* Change ADC state to error state */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);

/* Set ADC error code to ADC peripheral internal error */
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
}
}
}

/* Clear end of conversion flag of regular group if low power feature */
/* "LowPowerAutoWait " is disabled, to not interfere with this feature */
/* until data register is read using function HAL_ADC_GetValue(). */
if (hadc->Init.LowPowerAutoWait == DISABLE)
{
/* Clear regular group conversion flag */
__HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS));
}

/* Return function status */
return HAL_OK;
}

> when I created a new file and compiled it using the same settings and code, it worked fine

So, problem solved?

> i really don't know why..

I don't use Cube/CubeMX/CubeIDE so can't help with this, sorry.

JW

I'm using Keil5.

Also, I wrote the program by adding settings directly from the template without any initial settings, and I think I missed something in the process.

I checked more and found out that there was a problem like this.

 

111.jpg

The value of the CFGR1 register is returned to the address location of the register.

For reference, the value of the register is as follows in the regular program(operating normally).

222.jpg

This represents the Resister value of the ADC that I set, and I think the Resister value should come out as above in general. But why is the resister value the same as the address location?