<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.

Public Members
adc_reg_map * regs

Register map.

rcc_clk_id clk_id

RCC clock information.

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

struct adc_dev * ADC1

ADC1 device.

struct adc_dev * ADC2

ADC2 device.

struct adc_dev * 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().

Parameters:
  • dev -

    Device to enable.

See:

adc_read()

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

void adc_enable(const adc_dev * dev)

Enable an adc peripheral.

Parameters:
  • dev -

    ADC device to enable

void adc_disable(const adc_dev * dev)

Disable an ADC peripheral.

Parameters:
  • dev -

    ADC device to disable

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.

Parameters:
  • dev -

    ADC device to use for reading.

  • channel -

    channel to convert

Return:

conversion result

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:

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.

Parameters:
  • dev -

    ADC device

  • event -

    Event used to trigger the start of conversion.

See:

adc_extsel_event

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

STM32F1 Targets

adc_extsel_event enum

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 Targets

adc_extsel_event enum

STM32F2 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

adc_prescaler enum

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 Targets

adc_prescaler enum

STM32F2 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.

Parameters:
  • dev -

    adc device

  • smp_rate -

    sample rate to set

See:

adc_smp_rate

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

STM32F1 Targets

adc_smp_rate enum

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 Targets

adc_smp_rate enum

STM32F2 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 adc_dev * ignored, gpio_dev * gdev, uint8 bit)

STM32F1 only

The following routines are available only on STM32F1 targets.

void 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 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.

Public Members
__io uint32 SR

Status register.

__io uint32 CR1

Control register 1.

__io uint32 CR2

Control register 2.

__io uint32 SMPR1

Sample time register 1.

__io uint32 SMPR2

Sample time register 2.

__io uint32 JOFR1

Injected channel data offset register 1.

__io uint32 JOFR2

Injected channel data offset register 2.

__io uint32 JOFR3

Injected channel data offset register 3.

__io uint32 JOFR4

Injected channel data offset register 4.

__io uint32 HTR

Watchdog high threshold register.

__io uint32 LTR

Watchdog low threshold register.

__io uint32 SQR1

Regular sequence register 1.

__io uint32 SQR2

Regular sequence register 2.

__io uint32 SQR3

Regular sequence register 3.

__io uint32 JSQR

Injected sequence register.

__io uint32 JDR1

Injected data register 1.

__io uint32 JDR2

Injected data register 2.

__io uint32 JDR3

Injected data register 3.

__io uint32 JDR4

Injected data register 4.

__io uint32 DR

Regular data register.

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

struct stm32f2::adc_common_reg_map

ADC common register map type.

Public Members
__io uint32 CSR

Common status register.

__io uint32 CCR

Common control register.

__io uint32 CDR

Common regular data register for dual and triple modes.

Register Bit Definitions

TODO

Footnotes

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