<libmaple/adc.h>

Analog to Digital Conversion (ADC) support.

A common API for basic ADC functionality is available, but the characteristics of the ADC peripherals vary slightly across targets. To manage this, each target defines a small set of datatypes expressing its capabilities (namely adc_extsel_event, adc_smp_rate, and adc_prescaler).

Devices

The individual ADC peripherals have the following device struct.

struct adc_dev

ADC device type.

The available ADC peripherals vary by target. The complete list is ADC1, ADC2, and ADC3.

const struct adc_dev *stm32f1::ADC1

ADC1 device.

const struct adc_dev *stm32f1::ADC2

ADC2 device.

const struct adc_dev *stm32f1::ADC3

ADC3 device.

Functions

Activation and Deactivation

adc_enable_single_swstart() is simple, portable function, which enables an ADC and sets it up for its basic usage: performing single conversions using adc_read().

void adc_enable_single_swstart(const adc_dev *dev)

Enable an ADC and configure it for single conversion mode.

This function performs any initialization necessary to allow the ADC device to perform a single synchronous regular software triggered conversion, using adc_read().

See
adc_read()
Parameters
  • dev -

    Device to enable.

The precise software sequence used varies by target, so this is a good function to use if your program needs to support multiple MCUs. By default, Wirish calls adc_enable_single_swstart() on all available ADCs at init() time, so Wirish users don’t have to call this function.

There are several other lower-level routines used for activating and deactivating ADCs:

void adc_init(const adc_dev *dev)

Initialize an ADC peripheral.

Initializes the RCC clock line for the given peripheral. Resets ADC device registers.

Parameters
  • dev -

    ADC peripheral to initialize

static void adc_enable(const adc_dev *dev)

Enable an adc peripheral.

Parameters
  • dev -

    ADC device to enable

static void adc_disable(const adc_dev *dev)

Disable an ADC peripheral.

Parameters
  • dev -

    ADC device to disable

static void adc_disable_all(void)

Disable all ADC peripherals.

ADC Conversion

adc_read() is a simple function which starts conversion on a single ADC channel, blocks until it has completed, and returns the converted result. Don’t use the ADC device for any other purpose while it’s running.

uint16 adc_read(const adc_dev *dev, uint8 channel)

Perform a single synchronous software triggered conversion on a channel.

Return
conversion result
Parameters
  • dev -

    ADC device to use for reading.

  • channel -

    channel to convert

To use adc_read(), the device must be configured appropriately. You can do this with adc_enable_single_swstart().

Note that for an ADC device to perform conversion on a GPIO input (which is the usual case; the notable exception being taking temperature reading), the pin must be configured for analog conversion. Do this with adc_config_gpio().

Other routines helpful for ADC conversion:

static void adc_set_reg_seqlen(const adc_dev *dev, uint8 length)

Set the regular channel sequence length.

Defines the total number of conversions in the regular channel conversion sequence.

Parameters
  • dev -

    ADC device.

  • length -

    Regular channel sequence length, from 1 to 16.

void adc_set_extsel(const adc_dev *dev, adc_extsel_event event)

Set external event select for regular group.

See
adc_extsel_event
Parameters
  • dev -

    ADC device

  • event -

    Event used to trigger the start of conversion.

The last of these, adc_set_extsel(), takes a target-dependent adc_extsel_event argument.

STM32F1 Targets

enum stm32f1::adc_extsel_event

STM32F1 external event selectors for regular group conversion.

Some external events are only available on ADCs 1 and 2, others only on ADC3, while others are available on all three ADCs. Additionally, some events are only available on high- and XL-density STM32F1 MCUs, as they use peripherals only available on those MCU densities.

For ease of use, each event selector is given along with the ADCs it’s available on, along with any other availability restrictions.

See
adc_set_extsel()

Values:

ADC_EXT_EV_TIM1_CC1 = 0x00000

ADC1, ADC2: Timer 1 CC1 event.

ADC_EXT_EV_TIM1_CC2 = 0x20000

ADC1, ADC2: Timer 1 CC2 event.

ADC_EXT_EV_TIM2_CC2 = 0x60000

ADC1, ADC2: Timer 2 CC2 event.

ADC_EXT_EV_TIM3_TRGO = 0x80000

ADC1, ADC2: Timer 3 TRGO event.

ADC_EXT_EV_TIM4_CC4 = 0xA0000

ADC1, ADC2: Timer 4 CC4 event.

ADC_EXT_EV_EXTI11 = 0xC0000

ADC1, ADC2: EXTI11 event.

ADC_EXT_EV_TIM1_CC3 = 0x40000

ADC1, ADC2, ADC3: Timer 1 CC3 event.

ADC_EXT_EV_SWSTART = 0xE0000

ADC1, ADC2, ADC3: Software start.

ADC_EXT_EV_TIM3_CC1 = 0x00000

ADC3: Timer 3 CC1 event Availability: high- and XL-density.

ADC_EXT_EV_TIM2_CC3 = 0x20000

ADC3: Timer 2 CC3 event Availability: high- and XL-density.

ADC_EXT_EV_TIM8_CC1 = 0x60000

ADC3: Timer 8 CC1 event Availability: high- and XL-density.

ADC_EXT_EV_ADC3_TIM8_TRGO = 0x80000

ADC3: Timer 8 TRGO event Availability: high- and XL-density.

ADC_EXT_EV_TIM5_CC1 = 0xA0000

ADC3: Timer 5 CC1 event Availability: high- and XL-density.

ADC_EXT_EV_ADC12_TIM8_TRGO = 0xC0000

ADC1, ADC2: Timer 8 TRGO event Availability: high- and XL-density.

ADC_EXT_EV_TIM5_CC3 = 0xC0000

ADC3: Timer 5 CC3 event Availability: high- and XL-density.

STM32F2-F4 Targets

enum stm32f2_f4::adc_extsel_event

STM32F2-F4 external event selectors for regular group conversion.

See
adc_set_extsel()

Values:

ADC_EXT_EV_TIM1_CC1 = ADC_CR2_EXTSEL_TIM1_CC1
ADC_EXT_EV_TIM1_CC2 = ADC_CR2_EXTSEL_TIM1_CC2
ADC_EXT_EV_TIM1_CC3 = ADC_CR2_EXTSEL_TIM1_CC3
ADC_EXT_EV_TIM2_CC2 = ADC_CR2_EXTSEL_TIM2_CC2
ADC_EXT_EV_TIM2_CC3 = ADC_CR2_EXTSEL_TIM2_CC3
ADC_EXT_EV_TIM2_CC4 = ADC_CR2_EXTSEL_TIM2_CC4
ADC_EXT_EV_TIM1_TRGO = ADC_CR2_EXTSEL_TIM1_TRGO
ADC_EXT_EV_TIM3_CC1 = ADC_CR2_EXTSEL_TIM3_CC1
ADC_EXT_EV_TIM3_TRGO = ADC_CR2_EXTSEL_TIM3_TRGO
ADC_EXT_EV_TIM4_CC4 = ADC_CR2_EXTSEL_TIM4_CC4
ADC_EXT_EV_TIM5_CC1 = ADC_CR2_EXTSEL_TIM5_CC1
ADC_EXT_EV_TIM5_CC2 = ADC_CR2_EXTSEL_TIM5_CC2
ADC_EXT_EV_TIM5_CC3 = ADC_CR2_EXTSEL_TIM5_CC3
ADC_EXT_EV_TIM8_CC1 = ADC_CR2_EXTSEL_TIM8_CC1
ADC_EXT_EV_TIM8_TRGO = ADC_CR2_EXTSEL_TIM8_TRGO
ADC_EXT_EV_TIM1_EXTI11 = ADC_CR2_EXTSEL_TIM1_EXTI11

ADC Clock Prescaler

adc_set_prescaler() is available for setting the prescaler which determines the common ADC clock rate. (Wirish sets a sensible default for this, so Wirish users ordinarily don’t need to call this function.)

Warning

Increasing the ADC clock rate does speed conversion time, but the ADC peripherals have a maximum clock rate which must not be exceeded. Make sure to configure your system and ADC clocks to respect your device’s maximum rate.

void adc_set_prescaler(adc_prescaler pre)

Set the ADC prescaler.

This determines the ADC clock for all devices.

ADC prescaler values are target-dependent.

STM32F1 Targets

enum stm32f1::adc_prescaler

STM32F1 ADC prescalers, as divisors of PCLK2.

Values:

ADC_PRE_PCLK2_DIV_2 = RCC_ADCPRE_PCLK_DIV_2

PCLK2 divided by 2.

ADC_PRE_PCLK2_DIV_4 = RCC_ADCPRE_PCLK_DIV_4

PCLK2 divided by 4.

ADC_PRE_PCLK2_DIV_6 = RCC_ADCPRE_PCLK_DIV_6

PCLK2 divided by 6.

ADC_PRE_PCLK2_DIV_8 = RCC_ADCPRE_PCLK_DIV_8

PCLK2 divided by 8.

STM32F2-F4 Targets

enum stm32f2_f4::adc_prescaler

STM32F2-F4 ADC prescalers, as divisors of PCLK2.

Values:

ADC_PRE_PCLK2_DIV_2 = ADC_CCR_ADCPRE_PCLK2_DIV_2

PCLK2 divided by 2.

ADC_PRE_PCLK2_DIV_4 = ADC_CCR_ADCPRE_PCLK2_DIV_4

PCLK2 divided by 4.

ADC_PRE_PCLK2_DIV_6 = ADC_CCR_ADCPRE_PCLK2_DIV_6

PCLK2 divided by 6.

ADC_PRE_PCLK2_DIV_8 = ADC_CCR_ADCPRE_PCLK2_DIV_8

PCLK2 divided by 8.

ADC Sample Time

You can control the sampling time (in ADC cycles) for an entire ADC device using adc_set_sample_rate() [1]. This function only controls the sample rate; the total conversion time is equal to the sample time plus an additional number of ADC cycles. Consult the reference manual for your chip for more details.

Warning

Decreasing ADC sample time speeds conversion, but it also decreases the maximum allowable impedance of the voltage source you are measuring. If your voltage source has a high impedance (e.g. you’re measuring Vcc through a potentiometer), and your sample time is too low, you will get inaccurate results. Consult the datasheet for your target for more details.

Note

Wirish sets a sensible default sample rate to allow for high-impedance inputs at init() time, but Wirish users who know what they’re doing may want to call this function to speed up ADC conversion.

void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate)

Set the sample rate for all channels on an ADC device.

Don’t call this during conversion.

See
adc_smp_rate
Parameters
  • dev -

    adc device

  • smp_rate -

    sample rate to set

The adc_smp_rate argument to adc_set_sample_rate() is target-dependent.

STM32F1 Targets

enum stm32f1::adc_smp_rate

STM32F1 sample times, in ADC clock cycles.

These control the amount of time spent sampling the input voltage.

Values:

ADC_SMPR_1_5

1.5 ADC cycles

ADC_SMPR_7_5

7.5 ADC cycles

ADC_SMPR_13_5

13.5 ADC cycles

ADC_SMPR_28_5

28.5 ADC cycles

ADC_SMPR_41_5

41.5 ADC cycles

ADC_SMPR_55_5

55.5 ADC cycles

ADC_SMPR_71_5

71.5 ADC cycles

ADC_SMPR_239_5

239.5 ADC cycles

STM32F2-F4 Targets

enum stm32f2_f4::adc_smp_rate

STM32F2-F4 sample times, in ADC clock cycles.

Values:

ADC_SMPR_3

3 ADC cycles

ADC_SMPR_15

15 ADC cycles

ADC_SMPR_28

28 ADC cycles

ADC_SMPR_56

56 ADC cycles

ADC_SMPR_84

84 ADC cycles

ADC_SMPR_112

112 ADC cycles

ADC_SMPR_144

144 ADC cycles

ADC_SMPR_480

480 ADC cycles

Miscellaneous

void adc_foreach(void(*)(const adc_dev *) fn)

Call a function on all ADC devices.

Parameters
  • fn -

    Function to call on each ADC device.

void adc_config_gpio(const struct adc_dev *dev, struct gpio_dev *gdev, uint8 bit)

Configure a GPIO pin for ADC conversion.

Parameters
  • dev -

    ADC device to use for conversion (currently ignored on all targets).

  • gdev -

    GPIO device to configure.

  • bit -

    Bit on gdev to configure for ADC conversion.

STM32F1 only

The following routines are available only on STM32F1 targets.

static void stm32f1::adc_set_exttrig(const adc_dev *dev, uint8 enable)

Set external trigger conversion mode event for regular channels.

Availability: STM32F1.

Parameters
  • dev -

    ADC device

  • enable -

    If 1, conversion on external events is enabled; if 0, disabled.

adc_calibrate() performs calibration necessary on STM32F1 before using an ADC. Note that on STM32F1 targets, adc_enable_single_swstart() calls adc_calibrate(), so there’s no need to do it separately.

void stm32f1::adc_calibrate(const adc_dev *dev)

Calibrate an ADC peripheral.

Availability: STM32F1.

Parameters
  • dev -

    adc device

Register Maps

Individual ADC peripherals have the following register map. The base pointers are ADC1_BASE, ADC2_BASE, and ADC3_BASE.

struct adc_reg_map

ADC register map type.

On STM32F2-F4 targets, there is an additional common set of registers shared by all ADC peripherals. Its base pointer is ADC_COMMON_BASE.

struct stm32f2_f4::adc_common_reg_map

ADC common register map type.

Register Bit Definitions

TODO

Footnotes

[1]Per-channel sample time configuration is possible, but currently unsupported.