Skip to content

Commit c80ac26

Browse files
committed
STM32WL : ANALOGIN full support
1 parent ce6ff0a commit c80ac26

File tree

2 files changed

+76
-67
lines changed

2 files changed

+76
-67
lines changed

targets/TARGET_STM/TARGET_STM32WL/TARGET_STM32WL55xC/TARGET_NUCLEO_WL55JC/PeripheralPins.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ MBED_WEAK const PinMap PinMap_ADC[] = {
5555
{NC, NC, 0}
5656
};
5757

58-
// !!! SECTION TO BE CHECKED WITH DEVICE REFERENCE MANUAL
5958
MBED_WEAK const PinMap PinMap_ADC_Internal[] = {
60-
// {ADC_TEMP, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)},
61-
// {ADC_VREF, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 17, 0)},
62-
// {ADC_VBAT, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 18, 0)},
59+
{ADC_TEMP, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)},
60+
{ADC_VREF, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)},
61+
{ADC_VBAT, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)},
6362
{NC, NC, 0}
6463
};
6564

targets/TARGET_STM/TARGET_STM32WL/analogin_device.c

Lines changed: 73 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,35 @@
1919
#include "mbed_assert.h"
2020
#include "mbed_error.h"
2121
#include "mbed_debug.h"
22-
#include "mbed_wait_api.h"
2322
#include "cmsis.h"
2423
#include "pinmap.h"
2524
#include "PeripheralPins.h"
2625

27-
void analogin_init(analogin_t *obj, PinName pin)
26+
27+
#if STATIC_PINMAP_READY
28+
#define ANALOGIN_INIT_DIRECT analogin_init_direct
29+
void analogin_init_direct(analogin_t *obj, const PinMap *pinmap)
30+
#else
31+
#define ANALOGIN_INIT_DIRECT _analogin_init_direct
32+
static void _analogin_init_direct(analogin_t *obj, const PinMap *pinmap)
33+
#endif
2834
{
29-
uint32_t function = (uint32_t)NC;
35+
uint32_t function = (uint32_t)pinmap->function;
36+
37+
// Get the peripheral name from the pin and assign it to the object
38+
obj->handle.Instance = (ADC_TypeDef *)pinmap->peripheral;
3039

3140
// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
3241
// are described in PinNames.h and PeripheralPins.c
3342
// Pin value must be between 0xF0 and 0xFF
34-
if ((pin < 0xF0) || (pin >= 0x100)) {
43+
if ((pinmap->pin < 0xF0) || (pinmap->pin >= 0x100)) {
3544
// Normal channels
36-
// Get the peripheral name from the pin and assign it to the object
37-
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC);
38-
// Get the functions (adc channel) from the pin and assign it to the object
39-
function = pinmap_function(pin, PinMap_ADC);
45+
4046
// Configure GPIO
41-
pinmap_pinout(pin, PinMap_ADC);
47+
pin_function(pinmap->pin, pinmap->function);
48+
pin_mode(pinmap->pin, PullNone);
4249
} else {
4350
// Internal channels
44-
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal);
45-
function = pinmap_function(pin, PinMap_ADC_Internal);
4651
// No GPIO configuration for internal channels
4752
}
4853
MBED_ASSERT(obj->handle.Instance != (ADC_TypeDef *)NC);
@@ -51,58 +56,77 @@ void analogin_init(analogin_t *obj, PinName pin)
5156
obj->channel = STM_PIN_CHANNEL(function);
5257

5358
// Save pin number for the read function
54-
obj->pin = pin;
59+
obj->pin = pinmap->pin;
5560

5661
// Configure ADC object structures
5762
obj->handle.State = HAL_ADC_STATE_RESET;
58-
obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; // Asynchronous clock mode, input ADC clock
63+
obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
5964
obj->handle.Init.Resolution = ADC_RESOLUTION_12B;
6065
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
61-
obj->handle.Init.ScanConvMode = ADC_SCAN_DISABLE; // Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1)
62-
obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // On STM32L1xx ADC, overrun detection is enabled only if EOC selection is set to each conversion (or transfer by DMA enabled, this is not the case in this example).
66+
obj->handle.Init.ScanConvMode = ADC_SCAN_DISABLE;
67+
obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
6368
obj->handle.Init.LowPowerAutoWait = DISABLE;
64-
obj->handle.Init.ContinuousConvMode = DISABLE; // Continuous mode disabled to have only 1 conversion at each conversion trig
65-
obj->handle.Init.NbrOfConversion = 1; // Parameter discarded because sequencer is disabled
66-
obj->handle.Init.DiscontinuousConvMode = DISABLE; // Parameter discarded because sequencer is disabled
67-
//obj->handle.Init.NbrOfDiscConversion = 1; // Parameter discarded because sequencer is disabled
68-
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; // Software start to trig the 1st conversion manually, without external event
69+
obj->handle.Init.ContinuousConvMode = DISABLE;
70+
obj->handle.Init.NbrOfConversion = 1;
71+
obj->handle.Init.DiscontinuousConvMode = DISABLE;
72+
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
6973
obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
7074
obj->handle.Init.DMAContinuousRequests = DISABLE;
71-
obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // DR register is overwritten with the last conversion result in case of overrun
72-
obj->handle.Init.OversamplingMode = DISABLE; // No oversampling
73-
74-
// Enable ADC core clock
75-
__HAL_RCC_ADC_CLK_ENABLE();
76-
77-
// Enable ADC conversion clock.
78-
// Only necessary with asynchronous clock source
75+
obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
76+
obj->handle.Init.LowPowerAutoPowerOff = DISABLE;
77+
obj->handle.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_19CYCLES_5;
78+
obj->handle.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
79+
obj->handle.Init.OversamplingMode = DISABLE;
80+
obj->handle.Init.Oversampling.Ratio = 0; // workaround
81+
obj->handle.Init.Oversampling.RightBitShift = 0; // workaround
82+
obj->handle.Init.Oversampling.TriggeredMode = 0; // workaround
83+
obj->handle.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
84+
85+
// Enable ADC clock
7986
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK);
87+
__HAL_RCC_ADC_CLK_ENABLE();
8088

8189
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
82-
error("ADC initialization failed\r\n");
90+
error("Cannot initialize ADC");
8391
}
8492

8593
// ADC calibration is done only once
86-
//if (!HAL_ADCEx_Calibration_GetValue(&obj->handle, ADC_SINGLE_ENDED)) {
87-
// HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED);
88-
//}
94+
if (!HAL_ADCEx_Calibration_GetValue(&obj->handle)) {
95+
if (HAL_ADCEx_Calibration_Start(&obj->handle) != HAL_OK) {
96+
error("HAL_ADCEx_Calibration_Start error");
97+
}
98+
}
99+
}
100+
101+
void analogin_init(analogin_t *obj, PinName pin)
102+
{
103+
int peripheral;
104+
int function;
105+
106+
if ((pin < 0xF0) || (pin >= 0x100)) {
107+
peripheral = (int)pinmap_peripheral(pin, PinMap_ADC);
108+
function = (int)pinmap_find_function(pin, PinMap_ADC);
109+
} else {
110+
peripheral = (int)pinmap_peripheral(pin, PinMap_ADC_Internal);
111+
function = (int)pinmap_find_function(pin, PinMap_ADC_Internal);
112+
}
113+
114+
const PinMap static_pinmap = {pin, peripheral, function};
115+
116+
ANALOGIN_INIT_DIRECT(obj, &static_pinmap);
89117
}
90118

119+
91120
uint16_t adc_read(analogin_t *obj)
92121
{
93122
ADC_ChannelConfTypeDef sConfig = {0};
94123

95-
// Configure ADC channel
96124
sConfig.Rank = ADC_REGULAR_RANK_1;
97-
//sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
98-
//sConfig.SingleDiff = ADC_SINGLE_ENDED;
99-
//sConfig.OffsetNumber = ADC_OFFSET_NONE;
100-
//sConfig.Offset = 0;
125+
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
101126

102127
switch (obj->channel) {
103128
case 0:
104-
sConfig.Channel = ADC_CHANNEL_VREFINT;
105-
//sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // Minimum ADC sampling time when reading the internal reference voltage is 4us
129+
sConfig.Channel = ADC_CHANNEL_0;
106130
break;
107131
case 1:
108132
sConfig.Channel = ADC_CHANNEL_1;
@@ -138,55 +162,41 @@ uint16_t adc_read(analogin_t *obj)
138162
sConfig.Channel = ADC_CHANNEL_11;
139163
break;
140164
case 12:
141-
sConfig.Channel = ADC_CHANNEL_12;
165+
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
166+
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
142167
break;
143168
case 13:
144-
sConfig.Channel = ADC_CHANNEL_13;
169+
sConfig.Channel = ADC_CHANNEL_VREFINT;
170+
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
145171
break;
146172
case 14:
147-
sConfig.Channel = ADC_CHANNEL_14;
148-
break;
149-
case 15:
150-
sConfig.Channel = ADC_CHANNEL_15;
151-
break;
152-
case 16:
153-
sConfig.Channel = ADC_CHANNEL_16;
154-
break;
155-
case 17:
156-
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
157-
//sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // Minimum ADC sampling time when reading the temperature is 5us
158-
break;
159-
case 18:
160173
sConfig.Channel = ADC_CHANNEL_VBAT;
161-
//sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; // Minimum ADC sampling time when reading the VBAT is 12us
174+
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
162175
break;
163176
default:
164177
return 0;
165178
}
166179

167180
if (HAL_ADC_ConfigChannel(&obj->handle, &sConfig) != HAL_OK) {
168-
debug("ADC channel configuration failed\r\n");
181+
debug("HAL_ADC_ConfigChannel error\n");
169182
}
170183

171-
// Start conversion
172184
if (HAL_ADC_Start(&obj->handle) != HAL_OK) {
173-
debug("ADC start of conversion failed\r\n");
185+
debug("HAL_ADC_Start error\n");
174186
}
175187

176188
// Wait end of conversion and get value
177189
uint16_t adcValue = 0;
178-
if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) {
190+
if (HAL_ADC_PollForConversion(&obj->handle, 100) == HAL_OK) {
179191
adcValue = (uint16_t)HAL_ADC_GetValue(&obj->handle);
180192
}
181193

182-
if (HAL_ADC_Stop(&obj->handle) != HAL_OK) {
183-
debug("HAL_ADC_Stop failed\r\n");
184-
}
185-
186194
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE((&obj->handle)->Instance), LL_ADC_PATH_INTERNAL_NONE);
195+
187196
return adcValue;
188197
}
189198

199+
190200
const PinMap *analogin_pinmap()
191201
{
192202
return PinMap_ADC;

0 commit comments

Comments
 (0)