Skip to content
Snippets Groups Projects
Commit af9889f9 authored by Tobias Badertscher's avatar Tobias Badertscher Committed by Damien George
Browse files

stmhal/adc.c: Get ADC working on STM32L4 MCUs.

Fixing Issue #2243. Main problems were:

- HAL_ADC_GetState(adcHandle) may return other bits set (not only
  HAL_ADC_STATE_EOC_REG) when called - so I AND-ed it out as proposed by
  mattbrejza in Issue #2243.
- ADC Pin has to be configured as GPIO_MODE_ANALOG_ADC_CONTROL not only
  GPIO_MODE_ANALOG.
- Resolved ADC resolution L4 specific (Use L4 define ADC_RESOLUTION_12B).
- Changed setting of Init.EOCSelection toADC_EOC_SINGLE_CONV for L4.
- Added call to ADC_MultiModeTypeDef as this is done on a STM32Cube
  generated project too.
- Clean up: Configuration of ADC is done only in ONE function not the same
  is done in two functions.

Test is done on PA5 pin of STM32L4Discovery-Kit which is connected to the
DOWN button.

Thanks to mattbrejza for discovering the bug.
parent dfb81440
No related branches found
No related tags found
No related merge requests found
......@@ -131,7 +131,13 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
mp_hal_gpio_clock_enable(pin->gpio);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = pin->pin_mask;
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
#elif defined(MCU_SERIES_L4)
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
#else
#error Unsupported processor
#endif
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure);
}
......@@ -140,7 +146,6 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
ADC_HandleTypeDef *adcHandle = &adc_obj->handle;
adcHandle->Instance = ADCx;
adcHandle->Init.Resolution = ADC_RESOLUTION12b;
adcHandle->Init.ContinuousConvMode = DISABLE;
adcHandle->Init.DiscontinuousConvMode = DISABLE;
adcHandle->Init.NbrOfDiscConversion = 0;
......@@ -148,15 +153,19 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
adcHandle->Init.NbrOfConversion = 1;
adcHandle->Init.DMAContinuousRequests = DISABLE;
adcHandle->Init.EOCSelection = DISABLE;
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
adcHandle->Init.Resolution = ADC_RESOLUTION12b;
adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
adcHandle->Init.ScanConvMode = DISABLE;
adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
adcHandle->Init.EOCSelection = DISABLE;
#elif defined(MCU_SERIES_L4)
adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
adcHandle->Init.Resolution = ADC_RESOLUTION_12B;
adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
adcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE;
adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
adcHandle->Init.EOCSelection = ADC_EOC_SINGLE_CONV;
adcHandle->Init.ExternalTrigConv = ADC_SOFTWARE_START;
adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
adcHandle->Init.LowPowerAutoWait = DISABLE;
adcHandle->Init.Overrun = ADC_OVR_DATA_PRESERVED;
adcHandle->Init.OversamplingMode = DISABLE;
......@@ -165,30 +174,42 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
#endif
HAL_ADC_Init(adcHandle);
#if defined(MCU_SERIES_L4)
ADC_MultiModeTypeDef multimode;
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(adcHandle, &multimode) != HAL_OK)
{
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Can not set multimode on ADC1 channel: %d", adc_obj->channel));
}
#endif
}
STATIC void adc_config_channel(pyb_obj_adc_t *adc_obj) {
STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) {
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = adc_obj->channel;
sConfig.Channel = channel;
sConfig.Rank = 1;
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
#elif defined(MCU_SERIES_L4)
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
#else
#error Unsupported processor
#endif
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(&adc_obj->handle, &sConfig);
HAL_ADC_ConfigChannel(adc_handle, &sConfig);
}
STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
uint32_t rawValue = 0;
HAL_ADC_Start(adcHandle);
if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK && HAL_ADC_GetState(adcHandle) == HAL_ADC_STATE_EOC_REG) {
if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK
&& (HAL_ADC_GetState(adcHandle) & HAL_ADC_STATE_EOC_REG) == HAL_ADC_STATE_EOC_REG) {
rawValue = HAL_ADC_GetValue(adcHandle);
}
HAL_ADC_Stop(adcHandle);
......@@ -252,7 +273,7 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uin
STATIC mp_obj_t adc_read(mp_obj_t self_in) {
pyb_obj_adc_t *self = self_in;
adc_config_channel(self);
adc_config_channel(&self->handle, self->channel);
uint32_t data = adc_read_channel(&self->handle);
return mp_obj_new_int(data);
}
......@@ -313,7 +334,7 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
}
// configure the ADC channel
adc_config_channel(self);
adc_config_channel(&self->handle, self->channel);
// This uses the timer in polling mode to do the sampling
// TODO use DMA
......@@ -446,19 +467,7 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution) {
}
uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) {
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = channel;
sConfig.Rank = 1;
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
#elif defined(MCU_SERIES_L4)
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
#else
#error Unsupported processor
#endif
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(adcHandle, &sConfig);
adc_config_channel(adcHandle, channel);
return adc_read_channel(adcHandle);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment