Skip to content

Commit af9889f

Browse files
tobbaddpgeorge
authored andcommitted
stmhal/adc.c: Get ADC working on STM32L4 MCUs.
Fixing Issue adafruit#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 adafruit#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.
1 parent dfb8144 commit af9889f

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

stmhal/adc.c

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,13 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
131131
mp_hal_gpio_clock_enable(pin->gpio);
132132
GPIO_InitTypeDef GPIO_InitStructure;
133133
GPIO_InitStructure.Pin = pin->pin_mask;
134+
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
134135
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
136+
#elif defined(MCU_SERIES_L4)
137+
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
138+
#else
139+
#error Unsupported processor
140+
#endif
135141
GPIO_InitStructure.Pull = GPIO_NOPULL;
136142
HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure);
137143
}
@@ -140,23 +146,26 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
140146

141147
ADC_HandleTypeDef *adcHandle = &adc_obj->handle;
142148
adcHandle->Instance = ADCx;
143-
adcHandle->Init.Resolution = ADC_RESOLUTION12b;
144149
adcHandle->Init.ContinuousConvMode = DISABLE;
145150
adcHandle->Init.DiscontinuousConvMode = DISABLE;
146151
adcHandle->Init.NbrOfDiscConversion = 0;
147152
adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
148153
adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
149154
adcHandle->Init.NbrOfConversion = 1;
150155
adcHandle->Init.DMAContinuousRequests = DISABLE;
151-
adcHandle->Init.EOCSelection = DISABLE;
152156
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
157+
adcHandle->Init.Resolution = ADC_RESOLUTION12b;
153158
adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
154159
adcHandle->Init.ScanConvMode = DISABLE;
155160
adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
161+
adcHandle->Init.EOCSelection = DISABLE;
156162
#elif defined(MCU_SERIES_L4)
157-
adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
163+
adcHandle->Init.Resolution = ADC_RESOLUTION_12B;
164+
adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
158165
adcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE;
159-
adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
166+
adcHandle->Init.EOCSelection = ADC_EOC_SINGLE_CONV;
167+
adcHandle->Init.ExternalTrigConv = ADC_SOFTWARE_START;
168+
adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
160169
adcHandle->Init.LowPowerAutoWait = DISABLE;
161170
adcHandle->Init.Overrun = ADC_OVR_DATA_PRESERVED;
162171
adcHandle->Init.OversamplingMode = DISABLE;
@@ -165,30 +174,42 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
165174
#endif
166175

167176
HAL_ADC_Init(adcHandle);
177+
178+
#if defined(MCU_SERIES_L4)
179+
ADC_MultiModeTypeDef multimode;
180+
multimode.Mode = ADC_MODE_INDEPENDENT;
181+
if (HAL_ADCEx_MultiModeConfigChannel(adcHandle, &multimode) != HAL_OK)
182+
{
183+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Can not set multimode on ADC1 channel: %d", adc_obj->channel));
184+
}
185+
#endif
168186
}
169187

170-
STATIC void adc_config_channel(pyb_obj_adc_t *adc_obj) {
188+
STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) {
171189
ADC_ChannelConfTypeDef sConfig;
172190

173-
sConfig.Channel = adc_obj->channel;
191+
sConfig.Channel = channel;
174192
sConfig.Rank = 1;
175193
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
176194
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
177195
#elif defined(MCU_SERIES_L4)
178196
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
197+
sConfig.SingleDiff = ADC_SINGLE_ENDED;
198+
sConfig.OffsetNumber = ADC_OFFSET_NONE;
179199
#else
180200
#error Unsupported processor
181201
#endif
182202
sConfig.Offset = 0;
183203

184-
HAL_ADC_ConfigChannel(&adc_obj->handle, &sConfig);
204+
HAL_ADC_ConfigChannel(adc_handle, &sConfig);
185205
}
186206

187207
STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
188208
uint32_t rawValue = 0;
189209

190210
HAL_ADC_Start(adcHandle);
191-
if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK && HAL_ADC_GetState(adcHandle) == HAL_ADC_STATE_EOC_REG) {
211+
if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK
212+
&& (HAL_ADC_GetState(adcHandle) & HAL_ADC_STATE_EOC_REG) == HAL_ADC_STATE_EOC_REG) {
192213
rawValue = HAL_ADC_GetValue(adcHandle);
193214
}
194215
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
252273
STATIC mp_obj_t adc_read(mp_obj_t self_in) {
253274
pyb_obj_adc_t *self = self_in;
254275

255-
adc_config_channel(self);
276+
adc_config_channel(&self->handle, self->channel);
256277
uint32_t data = adc_read_channel(&self->handle);
257278
return mp_obj_new_int(data);
258279
}
@@ -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_
313334
}
314335

315336
// configure the ADC channel
316-
adc_config_channel(self);
337+
adc_config_channel(&self->handle, self->channel);
317338

318339
// This uses the timer in polling mode to do the sampling
319340
// TODO use DMA
@@ -446,19 +467,7 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution) {
446467
}
447468

448469
uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) {
449-
ADC_ChannelConfTypeDef sConfig;
450-
sConfig.Channel = channel;
451-
sConfig.Rank = 1;
452-
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
453-
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
454-
#elif defined(MCU_SERIES_L4)
455-
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
456-
#else
457-
#error Unsupported processor
458-
#endif
459-
sConfig.Offset = 0;
460-
HAL_ADC_ConfigChannel(adcHandle, &sConfig);
461-
470+
adc_config_channel(adcHandle, channel);
462471
return adc_read_channel(adcHandle);
463472
}
464473

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy