02、ADC 简介
ADC(模拟-数字转换器)是把连续变化的模拟信号(如声音、温度等)转换成数字信号的电子设备。它在传感器、音频设备、图像处理、通信系统等场景中被广泛应用。下面用更易懂的方式重新整理相关内容:
一、ADC的核心指标
分辨率
决定ADC能识别的最小信号差异。用"位数"表示,位数越高精度越高。例如:- 8位ADC能分辨256种电压值
- 12位ADC能分辨4096种电压值
常见的有8位、10位、12位等。
采样率
单位时间内能采集的信号次数(如每秒多少次)。数值越高,捕捉快速变化信号的能力越强。- 音频常用44.1kHz(每秒44100次)
- 高频信号可能需要百万级采样率。
信噪比(SNR)
衡量信号纯净度的指标。数值越高,说明信号中混入的杂音越少。转换速度
完成一次模数转换所需的时间。实时系统(如监控设备)需要更快的速度。输入范围
ADC能接受的模拟信号电压范围。例如:- 温度传感器可能只需0-5V
- 工业设备可能需要-10V到+10V的宽范围。
二、ADC的应用场景
- 音频处理
将麦克风的模拟声音信号转为数字信号,用于录音、语音助手、音乐播放等。 - 传感器数据采集
将温度、压力、光线等传感器的模拟信号转为数字,用于智能家居、工业控制、医疗设备等。 - 图像与视频处理
将摄像头的模拟图像信号转为数字格式,供手机、监控摄像头等设备处理。 - 数据监测系统
在工厂、实验室等场景中,实时采集并分析各种物理信号(如振动、电流等)。 - 通信系统
将接收的射频信号(如手机信号)转为数字信号,以便解码和传输。
三、瑞芯微的ADC配置
该开发板有两种ADC接口:
温度传感器ADC(TS-ADC)
- 支持2个测量通道
- 工作时钟不能超过800千赫兹(kHz)
- 专门用于温度检测。
逐次逼近型ADC(SAR-ADC)
- 提供6个独立输入通道
- 10位分辨率(可分辨1024种电压值)
- 工作时钟需低于13兆赫兹(MHz)
- 适用于多传感器信号采集(如压力、光线等)。
::: 使用时需注意:
根据传感器类型选择对应的ADC接口(温度用TS-ADC,其他信号用SAR-ADC)
设置合适的采样频率(不超过硬件限制)
确保输入信号在ADC支持的电压范围内。 :::
四、ADC配置指南
4.1 配置ADC的DTS节点
在RK3568芯片中,ADC的硬件信息定义在kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi
文件中,代码如下:
saradc: saradc@fe720000 {
compatible = "rockchip,rk3568-saradc", "rockchip,rk3399-saradc";
reg = <0x0 0xfe720000 0x0 0x100>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
#io-channel-cells = <1>;
clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
clock-names = "saradc", "apb_pclk";
resets = <&cru SRST_P_SARADC>;
reset-names = "saradc-apb";
status = "disabled";
};
2
3
4
5
6
7
8
9
10
11
你需要在自己的DTS文件(如**tspi-rk3566-core-v10.dtsi**
)中添加ADC的按键配置:
adc_keys: adc-keys {
compatible = "adc-keys"; // 匹配驱动的设备类型
io-channels = <&saradc 2>; // 使用ADC通道2(原示例可能有误,此处按注释修改为通道2)
io-channel-names = "buttons";// 给通道起别名,方便驱动识别
keyup-threshold-microvolt = <1800000>;// 松开按键时的电压阈值(单位微伏)
poll-interval = <100>; // 检测ADC的间隔时间(单位毫秒)
restart-key { // 定义一个按键节点
label = "restart"; // 按键名称
linux,code = <KEY_RESTART>; // 按键对应的系统代码(如复位键)
press-threshold-microvolt = <108>;// 按下时的电压阈值
};
};
2
3
4
5
6
7
8
9
10
11
12
13
4.2 驱动与DTS节点的匹配
驱动代码参考input/keyboard/adc-keys.c
,具体步骤如下:
步骤1:定义设备匹配表
在驱动代码中,声明一个结构体数组,用于匹配DTS中的compatible
属性:
#ifdef CONFIG_OF
static const struct of_device_id adc_keys_of_match[ ] = {
{ .compatible = "adc-keys", }, // 匹配DTS中的compatible值
{ }
};
MODULE_DEVICE_TABLE(of, adc_keys_of_match); // 注册匹配表
#endif
2
3
4
5
6
7
8
9
步骤2:将匹配表绑定到驱动
将上述匹配表关联到驱动的platform_driver
结构体中:
static struct platform_driver adc_keys_driver = {
.driver = {
.name = "adc_keys", // 驱动名称
.of_match_table = of_match_ptr(adc_keys_of_match), // 绑定匹配表
},
.probe = adc_keys_probe, // 设备初始化函数
};
module_platform_driver(adc_keys_driver); // 注册驱动
2
3
4
5
6
7
8
步骤3:解析DTS参数(在probe函数中)
在驱动的adc_keys_probe
函数中,通过以下步骤读取DTS配置:
static int adc_keys_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct adc_keys_state *st;
// 1. 分配内存
st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
if (!st) return -ENOMEM;
// 2. 获取ADC通道(通过DTS中的io-channel-names "buttons")
st->channel = devm_iio_channel_get(dev, "buttons");
if (IS_ERR(st->channel)) return PTR_ERR(st->channel);
// 3. 验证通道类型是否为电压型
if (iio_get_channel_type(st->channel) != IIO_VOLTAGE)
return -EINVAL;
// 4. 读取DTS参数
device_property_read_u32(dev, "keyup-threshold-microvolt", &st->keyup_voltage);
st->keyup_voltage /= 1000; // 单位转换(微伏转毫伏)
// 5. 加载按键映射(如restart-key的配置)
error = adc_keys_load_keymap(dev, st);
if (error) return error;
// 6. 初始化输入设备(如注册按键事件)
input = devm_input_allocate_device(dev);
if (!input) return -ENOMEM;
// 设置输入设备属性(名称、ID、事件类型等)
input->name = "ADC按键";
__set_bit(EV_KEY, input->evbit); // 支持按键事件
// ... 其他配置
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
关键点说明:
- DTS配置:通过
io-channels = <&saradc 2>
指定使用ADC通道2,press-threshold
和keyup-threshold
定义按键按压和释放的电压阈值。 - 驱动匹配:驱动通过
compatible = "adc-keys"
与DTS节点绑定,确保驱动能正确识别硬件。 - 参数解析:驱动在
probe
函数中通过设备属性(如keyup-threshold-microvolt
)读取配置,并初始化输入设备以处理按键事件。
以上步骤确保了硬件(ADC通道)与驱动的正确关联,并通过DTS参数动态配置按键行为。