ADC 驱动
本文档介绍 RK3588 SAR-ADC 控制器在 Linux 6.1 内核中的使用方法。ADC 在内核里由 IIO(Industrial I/O,内核为 ADC、加速度计这类数据采集设备提供的统一子系统)管理,本文同时介绍它的设备树配置。
适用范围: RK3588 Linux 6.1 Debian 12 / Ubuntu 22.04 系统,C-3588LQ V1.0 + SHIMETAPI-M5-R2A V1.0 底板。
1. 概念基础
1.1 ADC 是什么
ADC(Analog-to-Digital Converter,模数转换器)把模拟电压信号转换成数字值。RK3588 内置 SAR-ADC(逐次逼近型),特性:
| 特性 | 说明 |
|---|---|
| 分辨率 | 12 bit(4096 级) |
| 速率 | 最高 1 Msps |
| 通道数 | 多通道模拟输入 |
| 采样模式 | 单次 / 连续扫描 |
| 输入范围 | 0 ~ 3.3V(参考电压) |
1.2 应用场景
- 电源电压监测(多路电源轨)
- 模拟传感器采集(温度、光照、压力)
- 锂电池电量
- 4-20 mA 工业电流环
1.3 控制器基地址
| 控制器 | 基地址 |
|---|---|
| SARADC | 0xfe720000 |
2. 准备工作
2.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | C-3588LQ 核心板 + SHIMETAPI-M5-R2A 底板 | 1 | |
| 调试串口线 | USB 转 TTL(3.3V) | 1 | 波特率 1500000 |
| 电位器 | 10 kΩ | 1 | 用于 ADC 电压测试 |
| 万用表(可选) | 数字万用表 | 1 | 校准 |
| 杜邦线 | 母对母 | 若干 |
2.2 引脚
ADC 模拟输入引脚在底板原理图上有标注。注意:输入电压范围 0 ~ 3.3V,超压会损坏 ADC。
| 主控板引脚 | 外设引脚 | 功能说明 |
|---|---|---|
| ADC_INx(底板标注) | 电位器中间引脚 | ADC 模拟输入 |
| 3.3V | 电位器一端 | 参考电压 |
| GND | 电位器另一端 | 共地 |
3. 软件准备
3.1 内核配置
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_TRIGGERED_BUFFER=y
CONFIG_ROCKCHIP_SARADC=y /* RK3588 SAR-ADC IIO 驱动 */
CONFIG_OF=y驱动源码
drivers/iio/adc/rockchip_saradc.c。
3.2 设备树
saradc: sar@fe720000 {
compatible = "rockchip,rk3588-saradc", "rockchip,rk3399-saradc";
reg = <0x0 0xfe720000 0x0 0x10000>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
clock-names = "saradc", "apb_pclk";
resets = <&cru SRST_SARADC>;
reset-names = "saradc-apb";
#io-channel-cells = <1>;
status = "okay"; /* 需在板级 dts enable */
};4. 设备端 ADC 操作
4.1 查看 ADC IIO 设备
ls /sys/bus/iio/devices/实机输出如下:
iio:device0
iio_sysfs_trigger本机已加载 SAR-ADC,挂在
iio:device0。
4.2 查看 ADC 通道
ls /sys/bus/iio/devices/iio:device0/输出如下输出:
buffer
buffer0
dev
in_voltage0_raw
in_voltage1_raw
in_voltage2_raw
in_voltage3_raw
in_voltage4_raw
in_voltage5_raw
in_voltage6_raw本机 SARADC 暴露 7+ 个通道(in_voltage0~6_raw),每个文件读出 12-bit 原始值(0~4095)。
4.3 读取 ADC 原始值
# 通道 0 原始值(0 ~ 4095)
cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw读到的值输出:
2048
2048 / 4095 ≈ 50%,对应输入电压约 1.65 V(满量程 3.3V)。
4.4 读取 ADC 量纲(mV/LSB)
LSB 是最低有效位,也就是一个原始计数值对应的电压。scale 文件给出这个换算系数:
cat /sys/bus/iio/devices/iio:device0/in_voltage_scale输出输出:
0.805860约 0.806 mV/LSB。所以
in_voltage0_raw=2048实际电压 ≈ 2048 × 0.806 ≈ 1.65V。
4.5 计算实际电压
# Python 一行计算(电压 = raw * scale)
python3 -c "print(open('/sys/bus/iio/devices/iio:device0/in_voltage0_raw').read().strip() + ' * ' + open('/sys/bus/iio/devices/iio:device0/in_voltage_scale').read().strip() + ' = ' + str(int(open('/sys/bus/iio/devices/iio:device0/in_voltage0_raw').read()) * float(open('/sys/bus/iio/devices/iio:device0/in_voltage_scale').read()) + ' mV')"4.6 触发模式(连续采样)
# 启用通道 0 扫描
echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en
# 触发一次单次读取
cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw > /tmp/adc_sample.txt
# 用 sysfs trigger 持续采样
echo 0 > /sys/bus/iio/devices/iio_sysfs_trigger/trigger0/add_trigger_device5. 用户态工具(libiio)
除了直接读文件,也可以用 libiio 自带的命令行工具。
[电脑端/开发板] 安装 libiio-utils:
apt install -y libiio-utils# 一次性读取
iio_readdev -u local -d iio:device0 voltage0
# 连续读取触发模式(device buffer)
iio_readdev -u local -d iio:device0 voltage0 -b 1024 -t
voltage0等通道名需根据实际 iio 设备能力调整(工具按名字访问)。
6. 设备树引用 ADC
消费者节点通过 io-channels 引用 ADC:
some_node {
/* 引用 SARADC 通道 0,参考电压由 vcc_3v3_s0 提供 */
io-channels = <&saradc 0>;
io-channel-names = "adc0";
};PC 端修改后重编译烧录。
7. 代码解读
7.1 驱动注册
// drivers/iio/adc/rockchip_saradc.c(简化)
static struct platform_driver rockchip_saradc_driver = {
.probe = rockchip_saradc_probe,
.remove = rockchip_saradc_remove,
.driver = {
.name = "rockchip-saradc",
.of_match_table = rockchip_saradc_match,
},
};
static const struct of_device_id rockchip_saradc_match[] = {
{ .compatible = "rockchip,rk3588-saradc" },
{ /* sentinel */ }
};7.2 sysfs 调用链
用户空间: cat /sys/.../in_voltage0_raw
→ iio_read_channel_raw() /* IIO core */
→ rockchip_saradc_read_raw() /* Rockchip 驱动 */
→ 启动 ADC 转换
→ 等待中断 / 轮询完成
→ 读取 SARADC 数据寄存器8. 故障排除
8.1 读取始终为 0 或 4095
读数贴着量程两端,通常是节点没使能或被独占,按顺序检查:
# 检查 SARADC 节点状态
cat /proc/device-tree/saradc@fe720000/status
# 检查 ADC 时钟
cat /sys/kernel/debug/clk/clk_saradc/clk_rate
# 是否被某个 iio 消费者独占
cat /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en8.2 读数波动大
可以尝试:
- 多次采样取平均值
- 检查电源纹波
- 模拟信号走线尽量短,必要时加 RC 滤波
8.3 设备不存在
先看内核有没有识别到:
dmesg | grep -i saradc可能原因:设备树 status = "disabled" 或 CONFIG_ROCKCHIP_SARADC=m 但未加载。
