An Analog-to-Digital Converter (ADC) is a device that translates an analog voltage to a digital value that a microprocessor can understand.
The STMicroelectronics system-on-module has two ADC controllers, each with up to 20 channels. The ADC controllers are 16-bit successive approximation analog-to-digital converters.
Available ADC pins
On the ConnectCore MP15:
-
Dedicated analog pads ANA0 and ANA1 (ADC1 channels 0 and 1) are available at the LGA pads.
-
Other ADC1 and ADC2 channels are available at castellated and LGA pads, multiplexed with other functions. Check the Hardware reference manuals for information about pads and ADC channels.
On the ConnectCore MP15 Development Kit:
-
The following ADC channels are accessible on the GPIO expansion connector J41:
-
ANA0 (ADC1 channel 0)
-
ANA1 (ADC1 channel 1)
-
-
A number of pads of the ConnectCore MP15 can be configured as ADC channels (multiplexed with other functionality). On the ConnectCore MP15 Development Kit, some of them are accessible on connectors:
-
GPIOF 12 (ADC1 channel 6) on
MIKROBUS_RST
line, connector J30 -
GPIOF 13 (ADC2 channel 2) on
MIKROBUS_INT
line, connector J31
-
Kernel configuration
You can manage the STM32MP15 ADC drivers support through the following kernel configuration options:
-
STM32 ADC core driver (
CONFIG_STM32_ADC_CORE
) -
STM32 ADC driver (
CONFIG_STM32_ADC
)
These options are enabled as built-in on the default ConnectCore MP15 kernel configuration file.
Kernel driver
The ADC drivers are located at:
File | Description |
---|---|
STM32MP15 ADC core driver |
|
STM32MP15 ADC driver |
Device tree bindings and customization
The STM32MP15 ADC device tree binding is documented at
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
.
The device tree must contain entries for:
-
The ADC interface
-
The enabled channels
-
The IOMUX (for ADC channels on non-dedicated pads)
STM32MP15 ADC interface
adc: adc@48003000 {
compatible = "st,stm32mp1-adc-core";
reg = <0x48003000 0x400>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc ADC12>, <&rcc ADC12_K>;
clock-names = "bus", "adc";
interrupt-controller;
st,syscfg = <&syscfg>;
#interrupt-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
adc1: adc@0 {
compatible = "st,stm32mp1-adc";
#io-channel-cells = <1>;
reg = <0x0>;
interrupt-parent = <&adc>;
interrupts = <0>;
dmas = <&dmamux1 9 0x400 0x80000001>;
dma-names = "rx";
status = "disabled";
};
adc2: adc@100 {
compatible = "st,stm32mp1-adc";
#io-channel-cells = <1>;
reg = <0x100>;
interrupt-parent = <&adc>;
interrupts = <1>;
dmas = <&dmamux1 10 0x400 0x80000001>;
dma-names = "rx";
nvmem-cells = <&vrefint>;
nvmem-cell-names = "vrefint";
status = "disabled";
};
};
On the ConnectCore MP15 Development Kit, only ADC1 is enabled.
&adc {
/* ANA0, ANA1 are dedicated pins and don't need pinctrl */
vref-supply = <&vrefbuf>;
status = "okay";
adc1: adc@0 {
st,adc-channels = <0 1>;
/* 16.5 ck_cycles sampling time */
st,min-sample-time-nsecs = <400>;
status = "okay";
};
};
IOMUX configuration
You must configure the pads that are to be used as ADCs as ANALOG inputs. Pads ANA0 (ADC1 channel 0) and ANA1 (ADC1 channel 1) are dedicated ADC pins and do not need any IOMUX configuration.
Follow these steps to configure ADC channels on your custom design:
-
Identify the pins you want configured as ADC. Verify that they are ADC-capable and note the ADC channel they are connected to. You can find this information on the Hardware reference manuals.
-
Enable the desired channel indexes using the
st,adc-channels
property. -
Configure the IOMUX of the pins to operate as
ANALOG
. -
Compile the device tree and install it in your platform.
For example, ADC2 channel 2 is available on the ConnectCore MP15 Development Kit mikroBUS™ socket connector, which corresponds to pad GPIOF 13 of the CPU. To enable it:
&adc {
pinctrl-names = "default";
pinctrl-0 = <&ccmp15_adc_pins>;
status = "okay";
adc1: adc@0 {
st,adc-channels = <0 1>;
/* 16.5 ck_cycles sampling time */
st,min-sample-time-nsecs = <400>;
status = "okay";
};
adc2: adc@100 {
st,adc-channels = <2>;
st,min-sample-time-nsecs = <5000>;
status = "okay";
};
};
&pinctrl {
ccmp15_adc_pins: ccmp15_adc_pins-0 {
pins {
pinmux = <STM32_PINMUX('F', 13, ANALOG)>;
};
};
};
Voltage reference
The ADC block can use either the internal VREFBUF regulator or an external reference voltage supplied via the VREF+
pad.
VREFBUF
VREFBUF is a STM32MP15 internal voltage regulator supplied via the vdda
regulator of the PMIC.
The vdda
regulator is configured by default to 3.0 V.
You can configure VREFBUF to supply one of the following voltages to output at the VREF+
pin:
-
2.5 V
-
2.048 V
-
1.8 V
-
1.5 V
On the ConnectCore MP15 Development Kit device tree, VREFBUF is configured to output 2.5 V.
/*
* Internal VREFBUF can be set to 2.5 V, 2.048 V, 1.8 V or 1.5 V which are output
* at VREF+ pad.
* If you plan to use an external voltage reference, disable vrefbuf and change
* the ADC 'vref-supply' to the external regulator.
*/
&vrefbuf {
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
status = "okay";
};
If you plan to measure signals of less voltage, you can get more accurate results by changing the regulator-min-microvolt and regulator-max-microvolt properties to any of the other voltages.
|
External voltage reference
It’s possible to use an external voltage reference instead of the default internal VREFBUF. This external voltage reference cannot exceed the value of VDDA (3.0 V). To use an external voltage reference you need to make the following changes to your device tree:
-
Add a fixed regulator node for the external regulator, with its voltage: For example, for a 3.0 V reference:
/ { regulators { external_vref: regulator@99 { reg = <99>; compatible = "regulator-fixed"; regulator-name = "external-vref"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; }; }; };
-
Set the property
vref-supply
of theadc
node to this new regulator:&adc { vref-supply = <&external_vref>; };
-
Disable the internal
vrefbuf
regulator:&vrefbuf { status = "disabled"; };
-
Enable the VDDA regulator to remain on all the time. This is to prevent the analog block from draining voltage out of your external voltage reference.
&vdda { regulator-always-on; };
Formula
The value read on the ADC inputs responds to the formula:
\$V = (V_(RAW) + V_(OFFSET)) * V_(SCALE)\$
where:
-
VRAW is the input voltage converted by the ADC.
-
VOFFSET is the ADC voltage offset.
-
VSCALE is the ADC voltage scale value. This is automatically calculated basing on the Voltage reference on your device tree.
Using the ADCs
The ADC drivers are designed as standard Industrial I/O (IIO) device drivers that can be accessed from the sysfs or from user applications.
Sysfs access
When enabled, the ADC drivers create the corresponding device entries in the IIO sysfs directory (/sys/bus/iio/devices
).
To determine which entry corresponds to which driver, read the name
descriptors with:
# grep "" /sys/bus/iio/devices/iio\:device*/name
/sys/bus/iio/devices/iio:device0/name:40000000.timer:timer@1
/sys/bus/iio/devices/iio:device1/name:40002000.timer:timer@3
/sys/bus/iio/devices/iio:device2/name:48003000.adc:adc@0
In this example, device2
corresponds to ADC1.
The driver creates:
-
A file entry
in_voltage_offset
with the voltage offset. -
A file entry
in_voltage_scale
with the voltage scale. -
A file entry
in_voltageX_raw
for each ADC channel, where X corresponds to the channel number.
Read the input value of a channel with:
# cat /sys/bus/iio/devices/iio\:device2/in_voltage0_raw
37474
# cat /sys/bus/iio/devices/iio\:device2/in_voltage_offset
0
# cat /sys/bus/iio/devices/iio\:device2/in_voltage_scale
0.045776367
The returned value in in_voltageX_raw
is a decimal number with the result of the conversion.
In the example, and according to the Formula:
Sample application
An example application called apix-adc-example
is included in the dey-examples-digiapix recipe (part of dey-examples package) of the meta-digi layer.
This application shows how to access the ADCs using Digi APIx library on the ConnectCore MP15 platform.
Go to GitHub to see the application instructions and source code.
See ADC API for more information about the ADC APIx.