ADC¶
This chapter describes how to use the ADC (Analog‑to‑Digital Converter) functionality on the board.
Warning
Rockchip SARADC maximum input voltage is 1.8V – do not exceed this limit!
Allwinner GPADC maximum input voltage is 1.8V, LRADC maximum is 1.266V – do not exceed these limits!
The ADC pin information on the expansion pins for each platform is as follows:
| Motherboard | SoC | Platform | Kernel | Expansion Pins |
|---|---|---|---|---|
| K1 | RK3568 | Rockchip | 5.10 | SARADC X1 |
| K1B | RK3568 | Rockchip | 5.10 | SARADC X1 |
| K1Mini | RK3568 | Rockchip | 5.10 / 6.1 | SARADC X1 |
| K2B | H618 | Allwinner | 5.4 | None |
| K2C | H618 | Allwinner | 5.4 | None |
| K3 | RK3562 | Rockchip | 5.10 | SARADC X1 |
| K3B | RK3562 | Rockchip | 5.10 / 6.1 | SARADC X1 |
| K4B | T113 | Allwinner | 5.4 | GPADC X1 |
| K5C | A133 | Allwinner | 4.9 | LRADC X1 |
| K7 | RK3576 | Rockchip | 6.1 | SARADC X3 |
| K7C | RK3576 | Rockchip | 6.1 | SARADC X3 |
| K7S/F | RK3576 | Rockchip | 6.1 | None |
| K8 | RK3588 | Rockchip | 5.10 | SARADC X1 |
| K8D | RK3588S2 | Rockchip | 5.10 / 6.1 | SARADC X2 |
| K9 | T527 | Allwinner | 5.15 | None |
| K10B | A733 | Allwinner | 5.15 | GPADC X1 |
| K11C | RK3566 | Rockchip | 5.10 / 6.1 | SARADC X1 |
Terminology¶
| Term | Description |
|---|---|
| ADC | Analog‑to‑Digital Converter |
| SARADC | Successive Approximation ADC |
| GPADC | General Purpose ADC |
| LRADC | Low‑Rate ADC |
Specifications¶
| ADC | Resolution | Max Sample Rate | Input Voltage Range |
|---|---|---|---|
| SARADC | 12‑bit | 1 MHz | 0 ~ 1.8 V |
| GPADC | 12‑bit | 1 MHz | 0 ~ 1.8 V |
| LRADC | 6‑bit | 2 kHz | 0 ~ 1.266 V |
ADC Pin Location¶
- ADC pins
Note
The △ symbol on the board expansion pin header marks pin 1. Use the pin number silkscreen to locate the actual pin number.
K7 pinout example: The K7 board provides 3 ADC channels, mapped to pins 36 (SARADC_VIN4), 38 (SARADC_VIN5), and 40 (SARADC_VIN6).

DTS Configuration¶
DTS configuration differs across platforms; refer to the appropriate section for your board's platform.
Rockchip SARADC¶
Example SARADC node configuration for Rockchip platforms:
saradc: adc@ff280000 {
compatible = "rockchip,saradc";
reg = <0xff280000 0x1000>;
clocks = <&cru SCLK_SARADC>;
clock-names = "saradc";
resets = <&cru SRST_SARADC>;
reset-names = "saradc";
#io-channel-cells = <1>;
status = "okay";
};
Allwinner GPADC¶
Example GPADC node configuration for Allwinner platforms with Kernel 4.9:
/*
* channel_num: Maximum number of channels supported on the platform.
* channel_select: Channel enable selection. channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08
* channel_data_select: Channel data enable. channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
* channel_compare_select: Compare function enable channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
* channel_cld_select: Compare function low data enable detection: channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
* channel_chd_select: Compare function high data enable detection: channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
*/
gpadc:gpadc{
compatible = "allwinner,sunxi-gpadc"; // Identifies the device for driver binding
reg = <0x0 0x05070000 0x0 0x400>; // Register address
interrupts = <GIC_SPI 0 IRQ_TYPE_NONE>; // Interrupt configuration
clocks = <&clk_gpadc>; // Clock configuration
channel_num = <2>; // Channels used
channel_select = <0x05>; // Channel selection
channel_data_select = <0>; // Enable channel data
channel_compare_select = <0x05>; // Enable channel compare function
channel_cld_select = <0x05>; // Enable low‑data compare
channel_chd_select = <0>; // Enable high‑data compare
channel0_compare_lowdata = <1700000>; // Interrupt when data below this value
channel0_compare_higdata = <1200000>; // Interrupt when data above this value
channel1_compare_lowdata = <460000>;
channel1_compare_higdata = <1200000>;
channel0_compare_lowdata = <1500000>; // Interrupt when data below this value
channel0_compare_higdata = <1200000>; // Interrupt when data above this value
key_cnt = <5>; // Number of keys (only used when GPADC0 is used for buttons)
key0_vol = <210>; // Key voltage
key0_val = <115>; // Key value reported
key1_vol = <410>;
key1_val = <114>;
key2_vol = <590>;
key2_val = <139>;
key3_vol = <750>;
key3_val = <28>;
key4_vol = <880>;
key4_val = <102>;
status = "okay";
};
Example GPADC node configuration for Allwinner platforms with Kernel 5.15:
/*
* channel_num: Maximum number of channels supported on the platform.
* channel_select: Channel enable selection. channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08
* channel_data_select: Channel data enable. channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
* channel_compare_select: Compare function enable channel0:0x01
* channel1:0x02 channel2:0x04 channel3:0x08.
* channel_cld_select: Compare function low data enable detection: channel0:0x01
* channel1:0x02 channel2:0x04 channel3:0x08.
* channel_chd_select: Compare function high data enable detection: channel0:0x01
* channel1:0x02 channel2:0x04 channel3:0x08.
*/
gpadc0:gpadc{
channel_num = <10>; // Maximum number of channels (i.e., max keypad count)
channel_select = <0x3>; // Channel selection (channels 0 and 1)
channel_data_select = <0x3>; // Enable channel data
channel_compare_select = <0x3>; // Enable compare function
channel_cld_select = <0x3>; // Enable low‑data compare
channel_chd_select = <0x3>; // Enable high‑data compare
channel0_compare_lowdata = <1700000>; // Interrupt when channel0 data below this value
channel0_compare_higdata = <200000>; // Interrupt when channel0 data above this value
channel1_compare_lowdata = <1700000>; // Interrupt when channel1 data below this value
channel1_compare_higdata = <200000>; // Interrupt when channel1 data above this value
status = "okay";
// Multiple ADC channels can be used as buttons; configuration example below:
keyadc0 {
key_cnt = <5>; // Number of buttons
key0_vol = <115>; // Voltage when button pressed (in millivolts)
key0_val = <115>;
key1_vol = <240>;
key1_val = <114>;
key2_vol = <360>;
key2_val = <139>;
key3_vol = <480>;
key3_val = <28>;
key4_vol = <600>;
key4_val = <102>;
};
keyadc1 {
key_cnt = <5>;
key0_vol = <115>;
key0_val = <115>;
key1_vol = <240>;
key1_val = <114>;
key2_vol = <360>;
key2_val = <139>;
key3_vol = <480>;
key3_val = <28>;
key4_vol = <600>;
key4_val = <102>;
};
................
};
Allwinner LRADC¶
Example LRADC node configuration for Allwinner platforms:
sunxi_keyboard:keyboard {
compatible = "allwinner,keyboard";
reg = <0x0 0x01c21800 0x0 0x400>; /* Register address */
interrupts = <GIC_SPI 30 IRQ_TYPE_NONE>; /* Interrupt */
status = "okay"; /* Enable the node */
key_cnt = <5>;
key0 = <115 115>; /* First value: voltage in mV, second: key code */
key1 = <235 114>;
key2 = <330 139>;
key3 = <420 28>;
key4 = <520 102>;
};
Driver Paths¶
Driver paths for each platform (relative to SDK root):
// rk356x-linux / rk-linux6.1 / rk3576-linux / rk-android14.0
drivers/iio/adc/rockchip_saradc.c
// a133-linux / t113-linux / h618-android12.0
drivers/input/sensor/sunxi_gpadc.c
drivers/input/keyboard/sunxi-keyboard.c
// a733-linux / a733-android13.0
longan/bsp/drivers/gpadc/sunxi_gpadc.c
longan/bsp/drivers/lradc/sunxi-lradc.c
GPADC / LRADC Testing¶
List the input device event nodes:
Read raw event data using hexdump:
getevent is an Android command to view input device events:
evtest is an open‑source input event test tool for Linux:
SARADC Testing¶
On Rockchip platforms, SARADC is registered as an IIO (Industrial I/O) subsystem device. You can read ADC data as follows.
IIO Reading¶
List registered IIO devices:
List available interfaces for a specific IIO device (e.g., device 0):
Note
Key files under the interface:
in_voltageX_raw – X is the ADC channel number (e.g., 0, 6). Stores the raw ADC sample value.
in_voltage_scale – Voltage scale factor (V/LSB) used to convert raw value to actual voltage.
Voltage calculation formula:
Read the scale factor:
Read the raw value for channel 6:
Shell Script¶
The following script reads the voltage on channel 6. It outputs the raw value, scale factor, and computed voltage every second.
#!/bin/bash
echo "Press Ctrl+C to quit"
VOL_RAW="/sys/bus/iio/devices/iio:device0/in_voltage6_raw"
VOL_SCALE="/sys/bus/iio/devices/iio:device0/in_voltage_scale"
# Check required files accessibility
for file in "$VOL_RAW" "$VOL_SCALE"; do
[ ! -f "$file" ] || [ ! -r "$file" ] && { echo "Error: Cannot access $file" >&2; exit 1; }
done
while true; do
raw=$(cat "$VOL_RAW" | tr -d '\n\r ')
scale=$(cat "$VOL_SCALE" | tr -d '\n\r ')
voltage=$(awk -v r="$raw" -v s="$scale" 'BEGIN { printf "%.4f", (r * s) / 1000 }')
echo "vol_raw:$raw, vol_scale:$scale, vol:$voltage V"
sleep 1
done
Run it:
C Program¶
The following C program reads the voltage on channel 6:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#define VOL_RAW "/sys/bus/iio/devices/iio:device0/in_voltage6_raw"
#define VOL_SCALE "/sys/bus/iio/devices/iio:device0/in_voltage_scale"
// Handle Ctrl+C exit
void sigint_handler(int sig) {
(void)sig;
printf("\nExiting...\n");
exit(EXIT_SUCCESS);
}
// Read int from file
static int read_int(const char *path) {
FILE *fp = fopen(path, "r");
int val;
if (!fp || fscanf(fp, "%d", &val) != 1) {
perror("Read int failed");
exit(EXIT_FAILURE);
}
fclose(fp);
return val;
}
// Read float from file
static float read_float(const char *path) {
FILE *fp = fopen(path, "r");
float val;
if (!fp || fscanf(fp, "%f", &val) != 1) {
perror("Read float failed");
exit(EXIT_FAILURE);
}
fclose(fp);
return val;
}
int main() {
signal(SIGINT, sigint_handler);
printf("Press Ctrl+C to quit\n");
while (1) {
int raw = read_int(VOL_RAW);
float scale = read_float(VOL_SCALE);
printf("vol_raw:%d, vol_scale:%.6f, vol:%.4f V\n",
raw, scale, (raw * scale) / 1000.0f);
sleep(1);
}
}
Compile and run: