ADC (Analog-to-Digital Converter) 用于将模拟信号转换为数字值。本示例展示如何使用 Zephyr ADC API 进行多通道采样。
| 参数 | 说明 |
|---|---|
| 分辨率 (Resolution) | ADC 位数,如 10bit、12bit |
| 增益 (Gain) | 输入信号放大倍数 |
| 参考电压 (Reference) | ADC 满量程参考电压 |
| 采样时间 (Acquisition Time) | 采样电容充电时间 |
| 输入通道 | 正输入/负输入(差分模式) |
ADC值 = (Vin / Vref) * (2^resolution - 1)
Vin = ADC值 * Vref / (2^resolution - 1)
&adc {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
channel@0 {
reg = <0>; // 通道号
zephyr,gain = "ADC_GAIN_1"; // 增益 1x
zephyr,reference = "ADC_REF_INTERNAL"; // 内部参考电压
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN0>; // 正输入引脚
zephyr,resolution = <10>; // 10位分辨率
};
};
/ {
zephyr,user {
io-channels = <&adc 0>, <&adc 1>, <&adc 3>;
};
};
channel@3 {
reg = <3>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,input-positive = <NRF_SAADC_AIN5>; // 正输入
zephyr,input-negative = <NRF_SAADC_AIN6>; // 负输入
zephyr,resolution = <12>;
};
// 从设备树获取 ADC 通道规范
static const struct adc_dt_spec adc_channels[] = {
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, DT_SPEC_AND_COMMA)
};
// 单个通道
static const struct adc_dt_spec adc_chan = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
if (!adc_is_ready_dt(&adc_channels[i])) {
printk("ADC device not ready\n");
}
err = adc_channel_setup_dt(&adc_channels[i]);
if (err < 0) {
printk("Could not setup channel #%d (%d)\n", i, err);
}
uint16_t buf;
struct adc_sequence sequence = {
.buffer = &buf,
.buffer_size = sizeof(buf),
};
// 初始化序列
adc_sequence_init_dt(&adc_channels[i], &sequence);
// 读取
err = adc_read_dt(&adc_channels[i], &sequence);
if (err < 0) {
printk("Could not read (%d)\n", err);
}
int32_t val_mv = (int32_t)buf;
err = adc_raw_to_millivolts_dt(&adc_channels[i], &val_mv);
if (err == 0) {
printk(" = %d mV\n", val_mv);
}
ADC_GAIN_1_6 // 1/6 增益
ADC_GAIN_1_5 // 1/5 增益
ADC_GAIN_1_4 // 1/4 增益
ADC_GAIN_1_3 // 1/3 增益
ADC_GAIN_1_2 // 1/2 增益
ADC_GAIN_1 // 1x 增益(默认)
ADC_GAIN_2 // 2x 增益
ADC_GAIN_3 // 3x 增益
ADC_GAIN_4 // 4x 增益
ADC_REF_VDD_1 // VDD/1
ADC_REF_VDD_1_2 // VDD/2
ADC_REF_VDD_1_3 // VDD/3
ADC_REF_VDD_1_4 // VDD/4
ADC_REF_INTERNAL // 内部参考(通常 0.6V)
ADC_REF_EXTERNAL0 // 外部参考 0
ADC_REF_EXTERNAL1 // 外部参考 1
zephyr,resolution = <8>; // 8-bit: 0-255
zephyr,resolution = <10>; // 10-bit: 0-1023
zephyr,resolution = <12>; // 12-bit: 0-4095
zephyr,resolution = <14>; // 14-bit: 0-16383
zephyr,oversampling = <2>; // 2x 过采样
zephyr,oversampling = <4>; // 4x 过采样
zephyr,oversampling = <8>; // 8x 过采样
zephyr,oversampling = <16>; // 16x 过采样
zephyr,oversampling = <32>; // 32x 过采样
效果: 过采样可以降低噪声,提高有效位数。
zephyr,input-positive = <NRF_SAADC_AIN5>;
zephyr,input-negative = <NRF_SAADC_AIN6>;
if (adc_channels[i].channel_cfg.differential) {
val_mv = (int32_t)((int16_t)buf); // 有符号值
} else {
val_mv = (int32_t)buf; // 无符号值
}
差分模式特点:
struct adc_sequence sequence = {
.buffer = &buf,
.buffer_size = sizeof(buf),
};
adc_read_dt(&adc_chan, &sequence);
uint16_t buf[16];
struct adc_sequence sequence = {
.buffer = buf,
.buffer_size = sizeof(buf),
.options = NULL, // 可选配置
};
for (size_t i = 0; i < ARRAY_SIZE(adc_channels); i++) {
adc_sequence_init_dt(&adc_channels[i], &sequence);
adc_read_dt(&adc_channels[i], &sequence);
// 处理 buf...
}
// 设备树配置
channel@0 {
reg = <0>;
zephyr,gain = "ADC_GAIN_1_4"; // VDD/4 增益
zephyr,reference = "ADC_REF_INTERNAL"; // 0.6V 参考
zephyr,input-positive = <NRF_SAADC_VDD>; // VDD 通道
zephyr,resolution = <12>;
};
// 代码
int32_t vdd_mv = buf;
adc_raw_to_millivolts_dt(&adc_chan, &vdd_mv);
vdd_mv *= 4; // 补偿 1/4 增益
printk("Battery: %d mV\n", vdd_mv);
// NTC 热敏电阻分压测量
// VDD --- [NTC] --- AIN0 --- [10k] --- GND
int32_t adc_mv = buf;
adc_raw_to_millivolts_dt(&adc_chan, &adc_mv);
// 计算 NTC 电阻
float r_ntc = 10000.0 * adc_mv / (3300 - adc_mv);
// 根据 NTC 参数计算温度(简化)
float temp = 1.0 / (1.0/298.15 + log(r_ntc/10000)/3950) - 273.15;
CONFIG_ADC=y # 启用 ADC 驱动
CONFIG_ADC_ASYNC=y # 异步读取(可选)
CONFIG_ADC_NRFX_SAADC=y # Nordic SAADC 驱动
| 问题 | 答案 |
|---|---|
| ADC 分辨率在哪设? | 设备树 zephyr,resolution |
| 参考电压是多少? | 内部参考 0.6V,VDD 参考为 VDD/4 |
| 如何测量电池电压? | 使用 VDD 通道 + 1/4 增益 |
| 差分模式怎么配? | 设置 input-positive 和 input-negative |
| 如何提高精度? | 过采样 zephyr,oversampling |
adc_dt_spec 获取小白 🤖 2026-03-14