跳转至

ADC

Warning

Rockchip 平台 SARADC 最大采集电压 1.8V,严禁过压使用!
Allwinner 平台 GPADC 最大采集电压 1.8 V,LRADC 最大采集电压 1.266V,严禁过压使用!

Rockchip 平台拓展引脚 ADC 引脚信息如下:

主板 SOC 平台 拓展引脚
K1 RK3568 Rockchip SARADC X1
K1B RK3568 Rockchip SARADC X1
K3 RK3562 Rockchip SARADC X1
K7 RK3576 Rockchip SARADC X3
K7C RK3576 Rockchip SARADC X3
K8 RK3588 Rockchip SARADC X1

Allwinner 平台拓展引脚 ADC 引脚信息如下:

主板 SOC 平台 拓展引脚
K2B H618 Allwinner
K2C H618 Allwinner
K4B T113 Allwinner GRADC X1
K5C A133 Allwinner LRADC X1

术语说明

术语 说明
ADC Analog-to-Digital Converter
SARADC Successive approximation ADC
GPADC General Purpose ADC
LRADC Low Rate ADC

规格

ADC 分辨率 最大采样率 检测电压范围
SARADC 12-bit 1MHz 0~1.8V
GPADC 12-bit 1MHz 0~1.8V
LRADC 6-bit 2KHz 0~1.266 V

DTS 配置

不同平台 DTS 配置不相同,请根据主板对应平台查看对应的 DTS 节点配置。

Rockchip 平台 SARADC 的节点配置示例如下:

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 的节点配置示例如下:

/*
 * channel_num: Maxinum number of channels supported on the platform.
 * channel_select: channel enable slection. 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 setection: channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
 * channel_chd_select: compare function hig data enable setection: channel0:0x01 channel1:0x02 channel2:0x04 channel3:0x08.
 */
gpadc:gpadc{
    compatible = "allwinner,sunxi-gpadc"; //表征具体的设备,用于驱动和设备的绑定;
    reg = <0x0 0x05070000 0x0 0x400>; //设备使用的寄存器地址;
    interrupts = <GIC_SPI 0 IRQ_TYPE_NONE>; //设备使用的中断配置;
    clocks = <&clk_gpadc>; //设备使用的时钟配置
    channel_num = <2>; //使用的通道
    channel_select = <0x05>; //通道选择
    channel_data_select = <0>; //使能通道数据
    channel_compare_select = <0x05>; //使用通道比较功能
    channel_cld_select = <0x05>; //使用数据小于比较功能
    channel_chd_select = <0>; //使用数据大于比较功能
    channel0_compare_lowdata = <1700000>; //数据小于该值触发中断
    channel0_compare_higdata = <1200000>; //数据大于该值触发中断
    channel1_compare_lowdata = <460000>;
    channel1_compare_higdata = <1200000>;
    channel0_compare_lowdata = <1500000>; //数据小于该值触发中断
    channel0_compare_higdata = <1200000>; //数据大于该值触发中断
    key_cnt = <5>; //按键数量,注:以下部分只有GPADC0用于按键会用到
    key0_vol = <210>; //按键电压
    key0_val = <115>; //按键上报的值
    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";
}

Allwinner 平台 LRADC 的节点配置示例如下:

sunxi_keyboard:keyboard{
    compatible = "allwinner,keyboard";
    reg = <0x0 0x01c21800 0x0 0x400>; /* 寄存器地址 */
    interrupts = <GIC_SPI 30 IRQ_TYPE_NONE>; /* 中断 */
    status = "okay"; /* 使能该节点 */
    key_cnt = <5>;
    key0 = <115 115>; /*根据实际情况,左边115是电压,单位为mV,右边115为该电压对应的键值*/
    key1 = <235 114>;
    key2 = <330 139>;
    key3 = <420 28>;
    key4 = <520 102>;
};

驱动路径

Rockchip 平台 saradc 驱动位于 IIO(Industrial I/O)子系统框架下,负责将模拟信号转换为数字信号,供用户空间或应用程序读取。

drivers/iio/adc/rockchip_saradc.c

Allwinner 平台 GPADC 和 LRADC 驱动位于 Input 子系统框架下,负责将模拟信号转换为数字信号后,通过 Input 子系统上报,供用户空间或应用程序读取。

// GPADC
drivers/input/sensor/sunxi_gpadc.c
// LRADC
drivers/input/keyboard/sunxi-keyboard.c

ADC 引脚定位

  • ADC 引脚

Note

主板拓展引脚标注 △ 符号对应引脚图 1 号引脚,结合引脚数字丝印,确认实际引脚序号。

K7 引脚示意图:K7 主板配备 3 路 ADC,对应引脚 36(SARADC_VIN4)、38(SARADC_VIN5)、40(SARADC_VIN6)。

image-20251112185736716

GPADC/LRADC 测试

查看 ADC 模块的 event 节点:

cat /proc/bus/input/devices

hexdump 读取输入设备0数据:

hexdump /dev/input/event0

getevent 是 Android 系统中用于查看输入设备事件命令:

getevent -l

evtest 是 Linux 系统下开源的输入设备事件测试工具:

evtest /dev/input/event0

SARADC 测试

Rockchip 平台 SARADC 是注册为 iio 子系统设备,可以通过下面的方式进行读取 ADC 数据。

IIO 读取

列举系统中已注册的 IIO 设备:

ls /sys/bus/iio/devices/

查看目标 IIO 设备 0 的所有可操作接口:

ls /sys/bus/iio/devices/iio\:device0/

Note

接口下的关键节点
in_voltageX_raw: X 为 ADC 通道编号(如 0、6 等),存储对应通道的 ADC 原始采样数值。
in_voltage_scale: 电压换算比例系数(单位:V/LSB),用于将原始采样值转换为实际电压。

电压计算公式:

实际电压值 = in_voltageX_raw 读取值 × in_voltage_scale 读取值

读取电压比例系数(用于计算实际电压):

cat /sys/bus/iio/devices/iio:device0/in_voltage_scale

读取 IN6 通道的 ADC 原始采样值:

cat /sys/bus/iio/devices/iio:device0/in_voltage6_raw


Shell 脚本

通过脚本读取 IN6 通道电压,运行脚本后每秒输出 ADC 原始采样值,电压比例系数以及电压值。

#!/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

执行方式:

chmod +x adc_read.sh
./adc_read.sh

C 程序

通过 C 程序读取 IN6 通道电压:

#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);
    }
}

执行方式:

gcc adc_read.c -o adc_read
chmod +x adc_read
./adc_read