Skip to content

Commit ac78e30

Browse files
committed
[ADC] Add internal channels support
Fix stm32duino#474 Signed-off-by: Frederic.Pillon <[email protected]>
1 parent 57e3b74 commit ac78e30

File tree

5 files changed

+138
-9
lines changed

5 files changed

+138
-9
lines changed

cores/arduino/pins_arduino.c

+27
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,33 @@ WEAK uint32_t pinNametoDigitalPin(PinName p)
3535
return i;
3636
}
3737

38+
PinName analogInputToPinName(uint32_t pin)
39+
{
40+
PinName pn = digitalPinToPinName(analogInputToDigitalPin(pin));
41+
if (pn == NC) {
42+
switch (pin) {
43+
#ifdef ATEMP
44+
case ATEMP:
45+
pn = PADC_TEMP;
46+
break;
47+
#endif
48+
#ifdef AVREF
49+
case AVREF:
50+
pn = PADC_VREF;
51+
break;
52+
#endif
53+
#ifdef AVBAT
54+
case AVBAT:
55+
pn = PADC_VBAT;
56+
break;
57+
#endif
58+
default:
59+
break;
60+
}
61+
}
62+
return pn;
63+
}
64+
3865
#ifdef __cplusplus
3966
}
4067
#endif

cores/arduino/pins_arduino.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ static const uint8_t SCK = PIN_SPI_SCK;
201201
static const uint8_t SDA = PIN_WIRE_SDA;
202202
static const uint8_t SCL = PIN_WIRE_SCL;
203203

204+
// ADC internal channels (not a pins)
205+
// Only used for analogRead()
206+
#ifdef ADC_CHANNEL_TEMPSENSOR
207+
#define ATEMP (NUM_DIGITAL_PINS + 1)
208+
#endif
209+
#ifdef ADC_CHANNEL_VREFINT
210+
#define AVREF (NUM_DIGITAL_PINS + 2)
211+
#endif
212+
#ifdef ADC_CHANNEL_VBAT
213+
#define AVBAT (NUM_DIGITAL_PINS + 3)
214+
#endif
215+
204216
#ifdef __cplusplus
205217
extern "C" {
206218
#endif
@@ -218,7 +230,8 @@ uint32_t pinNametoDigitalPin(PinName p);
218230
// Used by analogRead api to have A0 == 0
219231
#define analogInputToDigitalPin(p) (((uint32_t)p < NUM_ANALOG_INPUTS) ? (p+A0) : p)
220232
// Convert an analog pin number Axx to a PinName PX_n
221-
#define analogInputToPinName(p) (digitalPinToPinName(analogInputToDigitalPin(p)))
233+
PinName analogInputToPinName(uint32_t pin);
234+
222235
// All pins could manage EXTI
223236
#define digitalPinToInterrupt(p) (digitalPinIsValid(p) ? p : NOT_AN_INTERRUPT)
224237

cores/arduino/stm32/PinNames.h

+11
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,17 @@ typedef enum {
207207
PK_13 = (PortK << 4) + 0x0D,
208208
PK_14 = (PortK << 4) + 0x0E,
209209
PK_15 = (PortK << 4) + 0x0F,
210+
#endif
211+
// Specific pin name
212+
PADC_OFFSET = 0x100,
213+
#ifdef ADC_CHANNEL_TEMPSENSOR
214+
PADC_TEMP,
215+
#endif
216+
#ifdef ADC_CHANNEL_VREFINT
217+
PADC_VREF,
218+
#endif
219+
#ifdef ADC_CHANNEL_VBAT
220+
PADC_VBAT,
210221
#endif
211222
// Specific pin name define in the variant
212223
#if __has_include("PinNamesVar.h")

cores/arduino/stm32/analog.c

+79-8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,35 @@ static PinName g_current_pin = NC;
7070
#endif
7171
#endif /* !ADC_SAMPLINGTIME */
7272

73+
/*
74+
* Minimum ADC sampling time is required when reading
75+
* internal channels so set it to max possible value.
76+
* It can be defined more precisely by defining:
77+
* ADC_SAMPLINGTIME_INTERNAL
78+
* to the desired ADC sample time.
79+
*/
80+
#ifndef ADC_SAMPLINGTIME_INTERNAL
81+
#if defined(ADC_SAMPLETIME_480CYCLES)
82+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_480CYCLES
83+
#elif defined(ADC_SAMPLETIME_384CYCLES)
84+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_384CYCLES
85+
#elif defined(ADC_SAMPLETIME_810CYCLES_5)
86+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_810CYCLES_5
87+
#elif defined(ADC_SAMPLETIME_640CYCLES_5)
88+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_640CYCLES_5
89+
#elif defined(ADC_SAMPLETIME_601CYCLES_5)
90+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_601CYCLES_5
91+
#elif defined(ADC_SAMPLETIME_247CYCLES_5)
92+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_247CYCLES_5
93+
#elif defined(ADC_SAMPLETIME_239CYCLES_5)
94+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_239CYCLES_5
95+
#elif defined(ADC_SAMPLETIME_160CYCLES_5)
96+
#define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_160CYCLES_5
97+
#else
98+
#error "ADC sampling time could not be defined for internal channels!"
99+
#endif
100+
#endif /* !ADC_SAMPLINGTIME_INTERNAL */
101+
73102
#ifndef ADC_CLOCK_DIV
74103
#ifdef ADC_CLOCK_SYNC_PCLK_DIV4
75104
#define ADC_CLOCK_DIV ADC_CLOCK_SYNC_PCLK_DIV4
@@ -204,6 +233,32 @@ static uint32_t get_adc_channel(PinName pin)
204233
}
205234
return channel;
206235
}
236+
237+
static uint32_t get_adc_internal_channel(PinName pin)
238+
{
239+
uint32_t channel = 0;
240+
switch (pin) {
241+
#ifdef ADC_CHANNEL_TEMPSENSOR
242+
case PADC_TEMP:
243+
channel = ADC_CHANNEL_TEMPSENSOR;
244+
break;
245+
#endif
246+
#ifdef ADC_CHANNEL_VREFINT
247+
case PADC_VREF:
248+
channel = ADC_CHANNEL_VREFINT;
249+
break;
250+
#endif
251+
#ifdef ADC_CHANNEL_VBAT
252+
case PADC_VBAT:
253+
channel = ADC_CHANNEL_VBAT;
254+
break;
255+
#endif
256+
default:
257+
channel = 0;
258+
break;
259+
}
260+
return channel;
261+
}
207262
#endif /* HAL_ADC_MODULE_ENABLED */
208263

209264
#ifdef HAL_TIM_MODULE_ENABLED
@@ -449,7 +504,9 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
449504
#endif
450505

451506
/* Configure ADC GPIO pin */
452-
pinmap_pinout(g_current_pin, PinMap_ADC);
507+
if (g_current_pin < PADC_OFFSET) {
508+
pinmap_pinout(g_current_pin, PinMap_ADC);
509+
}
453510
}
454511

455512
/**
@@ -554,8 +611,21 @@ uint16_t adc_read_value(PinName pin)
554611
ADC_HandleTypeDef AdcHandle = {};
555612
ADC_ChannelConfTypeDef AdcChannelConf = {};
556613
__IO uint16_t uhADCxConvertedValue = 0;
614+
uint32_t samplingTime = ADC_SAMPLINGTIME;
615+
uint32_t channel = 0;
557616

558-
AdcHandle.Instance = pinmap_peripheral(pin, PinMap_ADC);
617+
if (pin > PADC_OFFSET) {
618+
#if defined(STM32H7xx)
619+
AdcHandle.Instance = ADC3;
620+
#else
621+
AdcHandle.Instance = ADC1;
622+
#endif
623+
channel = get_adc_internal_channel(pin);
624+
samplingTime = ADC_SAMPLINGTIME_INTERNAL;
625+
} else {
626+
AdcHandle.Instance = pinmap_peripheral(pin, PinMap_ADC);
627+
channel = get_adc_channel(pin);
628+
}
559629

560630
if (AdcHandle.Instance == NP) {
561631
return 0;
@@ -613,16 +683,16 @@ uint16_t adc_read_value(PinName pin)
613683
#endif
614684

615685
#if defined(STM32F0xx)
616-
AdcHandle.Init.SamplingTimeCommon = ADC_SAMPLINGTIME;
686+
AdcHandle.Init.SamplingTimeCommon = samplingTime;
617687
#endif
618688
#if defined(STM32G0xx)
619-
AdcHandle.Init.SamplingTimeCommon1 = ADC_SAMPLINGTIME; /* Set sampling time common to a group of channels. */
620-
AdcHandle.Init.SamplingTimeCommon2 = ADC_SAMPLINGTIME; /* Set sampling time common to a group of channels, second common setting possible.*/
689+
AdcHandle.Init.SamplingTimeCommon1 = samplingTime; /* Set sampling time common to a group of channels. */
690+
AdcHandle.Init.SamplingTimeCommon2 = samplingTime; /* Set sampling time common to a group of channels, second common setting possible.*/
621691
AdcHandle.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
622692
#endif
623693
#if defined(STM32L0xx)
624694
AdcHandle.Init.LowPowerFrequencyMode = DISABLE; /* To be enabled only if ADC clock < 2.8 MHz */
625-
AdcHandle.Init.SamplingTime = ADC_SAMPLINGTIME;
695+
AdcHandle.Init.SamplingTime = samplingTime;
626696
#endif
627697
#if !defined(STM32F0xx) && !defined(STM32F1xx) && !defined(STM32F2xx) && \
628698
!defined(STM32F3xx) && !defined(STM32F4xx) && !defined(STM32F7xx) && \
@@ -649,7 +719,8 @@ uint16_t adc_read_value(PinName pin)
649719
return 0;
650720
}
651721

652-
AdcChannelConf.Channel = get_adc_channel(pin); /* Specifies the channel to configure into ADC */
722+
AdcChannelConf.Channel = channel; /* Specifies the channel to configure into ADC */
723+
653724
#if defined(STM32L4xx) || defined(STM32WBxx)
654725
if (!IS_ADC_CHANNEL(&AdcHandle, AdcChannelConf.Channel)) {
655726
return 0;
@@ -662,7 +733,7 @@ uint16_t adc_read_value(PinName pin)
662733
AdcChannelConf.Rank = ADC_REGULAR_RANK_1; /* Specifies the rank in the regular group sequencer */
663734
#if !defined(STM32L0xx)
664735
#if !defined(STM32G0xx)
665-
AdcChannelConf.SamplingTime = ADC_SAMPLINGTIME; /* Sampling time value to be set for the selected channel */
736+
AdcChannelConf.SamplingTime = samplingTime; /* Sampling time value to be set for the selected channel */
666737
#else
667738
AdcChannelConf.SamplingTime = ADC_SAMPLINGTIME_COMMON_1; /* Sampling time value to be set for the selected channel */
668739
#endif

keywords.txt

+7
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ A20 LITERAL1
209209
A21 LITERAL1
210210
A22 LITERAL1
211211
A23 LITERAL1
212+
ATEMP LITERAL1
213+
AVREF LITERAL1
214+
AVBAT LITERAL1
212215
PIN_A0 LITERAL1
213216
PIN_A1 LITERAL1
214217
PIN_A2 LITERAL1
@@ -712,6 +715,10 @@ PK_12 LITERAL1
712715
PK_13 LITERAL1
713716
PK_14 LITERAL1
714717
PK_15 LITERAL1
718+
PADC_OFFSET LITERAL1
719+
PADC_TEMP LITERAL1
720+
PADC_VREF LITERAL1
721+
PADC_VBAT LITERAL1
715722

716723
# Port Name
717724
PortName KEYWORD3

0 commit comments

Comments
 (0)