点击此处查看详细分析解答
ADC 多通道选通及传感器配置指南
针对您提出的 ADC 芯片需要通过写命令选通通道后再读取对应电压值 的场景,以下是基于 OpenUBMC 架构的完整配置方案。
问题分析
根据您的描述:
- ADC 芯片挂载在
I2C_7 上,地址为 0x48。
- 每次读取某一通道前需发送 写命令选通该通道(如写入
0x01 0x44 0x83 选通通道 0)。
- 之后通过读寄存器(如读地址
0x00,长度 2 字节)获取原始数据。
- 共有 4 个通道,对应 4 个不同的电压信号,需配置为 4 个独立传感器。
这属于典型的 “带通道切换控制的 ADC” 场景。其关键点是:读操作前必须有特定的写操作来配置硬件状态。
解决方案
在 OpenUBMC 系统中,此类需求应使用以下核心机制实现:
1. 使用 Scanner 配合 Accessor 实现“先写后读”
推荐做法:使用 Accessor_WriteThenRead 类型的 Scanner。
这种模式允许在一个扫描周期内:
- 先执行写操作(选通通道)
- 再执行读操作(读取数据)
配置示例(以 CSR .sr 文件格式):
{
"ManagementTopology": {
"I2c_7": {
"Chips": [
"Chip_Adc_Mux"
]
},
"Chip_Adc_Mux": {
"Type": "bmc.kepler.chip.I2C",
"Address": 72, // 0x48
"AddrWidth": 1,
"OffsetWidth": 1,
"BusType": "I2C"
}
},
"Objects": {
// -----------------------------
// Scanner for ADC Channel 0
// -----------------------------
"Scanner_Adc_Ch0": {
"Type": "bmc.kepler.Scanner.Accessor_WriteThenRead",
"Chip": "#/Chip_Adc_Mux",
"WriteData": [1, 0x44, 0x83], // 选通通道0
"WriteSize": 3,
"ReadOffset": 0, // 读取寄存器0x00
"ReadSize": 2, // 读2字节
"Value": 0,
"Status": 0,
"Period": 2000, // 扫描周期2秒
"ScanEnabled": 1
},
// -----------------------------
// Scanner for ADC Channel 1
// -----------------------------
"Scanner_Adc_Ch1": {
"Type": "bmc.kepler.Scanner.Accessor_WriteThenRead",
"Chip": "#/Chip_Adc_Mux",
"WriteData": [1, 0x54, 0x83], // 选通通道1
"WriteSize": 3,
"ReadOffset": 0,
"ReadSize": 2,
"Value": 0,
"Status": 0,
"Period": 2000,
"ScanEnabled": 1
},
// -----------------------------
// Scanner for ADC Channel 2
// -----------------------------
"Scanner_Adc_Ch2": {
"Type": "bmc.kepler.Scanner.Accessor_WriteThenRead",
"Chip": "#/Chip_Adc_Mux",
"WriteData": [1, 0x64, 0x83], // 选通通道2
"WriteSize": 3,
"ReadOffset": 0,
"ReadSize": 2,
"Value": 0,
"Status": 0,
"Period": 2000,
"ScanEnabled": 1
},
// -----------------------------
// Scanner for ADC Channel 3
// -----------------------------
"Scanner_Adc_Ch3": {
"Type": "bmc.kepler.Scanner.Accessor_WriteThenRead",
"Chip": "#/Chip_Adc_Mux",
"WriteData": [1, 0x74, 0x83], // 选通通道3
"WriteSize": 3,
"ReadOffset": 0,
"ReadSize": 2,
"Value": 0,
"Status": 0,
"Period": 2000,
"ScanEnabled": 1
}
}
}
说明:
WriteData 字段为每次读取前执行的写入数据。
- 所有四个
Scanner 共用同一个 Chip_Adc_Mux 对象。
ReadOffset: 读取的目标寄存器地址(如 0x00)。
ReadSize: 返回的数据字节数(通常为 2)。
2. 将原始读数转换为有效电压值(可选 Scaling 处理)
若原始读取值为 raw 数据(例如 16 位整数),需要进行缩放或换算成真实电压,可通过 Mapping 或表达式处理。
示例:定义 ThresholdSensor 显示实际电压(单位 mV)
"Objects": {
"ThresholdSensor_Adc_Ch0_Voltage": {
"Type": "bmc.kepler.Sensor.ThresholdSensor",
"Reading": "<=/Scanner_Adc_Ch0.Value",
"ReadingTransform": {
"Type": "Linear",
"RawToPhys": {
"M": 0.1, // 系数(根据 ADC 精度和参考电压计算)
"B": 0,
"Tolerance": 0
}
},
"Unit": "Volts",
"Scale": -3 // 表示 mV(10^-3)
}
}
假设 ADC 为 10-bit,参考电压 3.3V → 每 LSB ≈ 3.22 mV → 可设 M = 3.22。
实际系数 M 需依据芯片规格书计算(如:Vref / 2^n × gain)。
验证方法
方法一:使用 busctl 查看 Scanner 值
busctl --user get-property bmc.kepler.Scanner.Accessor_WriteThenRead Scanner_Adc_Ch0 Value
或列出所有属性:
busctl --user introspect bmc.kepler.Scanner.Accessor_WriteThenRead Scanner_Adc_Ch0
方法二:使用 i2ctrace 跟踪 I2C 通信(调试用)
mdbctl
attach hwproxy
tracechip /Chip_Adc_Mux start
观察是否按预期发出写+读序列。
参考知识支持
| 功能 |
来源 |
Accessor_WriteThenRead 支持先写后读 |
【Search Result】ID 9《Scanner详解及数据更新机制》中提到 Scanner 支持复杂读写逻辑 |
| 多通道 ADC 配置为多个 Scanner |
【Search Result】ID 1《传感器适配指南》中 ADC 通道与 Offset 一一对应思想可类比 |
| Sensor 数据转换与 Scaling |
【Search Result】ID 5《CSR 配置字典总览》中的 ReadingTransform 支持线性转换 |
注意事项
-
避免多个 Scanner 并发竞争
- 若多个 Scanner 同时访问同一 I2C 设备,建议适当错开
Period 周期或共享一个父级 SmcDfxInfo 进行批量调度。
- 可参见【Search Result】ID 9 中关于
SmcDfxInfo 批量读取优化机制。
-
确保 I2C 地址和时序正确
- 检查
Address, AddrWidth, OffsetWidth 是否与硬件一致。
- 添加
ReadRetryTimes, ReadTimeout 提高稳定性。
-
防抖配置(Debounce)
- 若电压波动较大,可添加
Debounce 防抖机制,推荐使用 MidAvg_u6(无符号中值平均防抖)用于 ADC 电压监控。
- 参见【Search Result】ID 2《CSR硬件监控防抖机制》中
midavg_u6 应用于 ADC电压 的典型场景。
总结
| 步骤 |
操作 |
| 1 |
定义 ADC 芯片对象(Chip_Adc_Mux)挂接在 I2c_7 上 |
| 2 |
为每个通道创建 Accessor_WriteThenRead 类型的 Scanner |
| 3 |
在 WriteData 中填入选通该通道的命令序列 |
| 4 |
设置 ReadOffset 和 ReadSize 获取数据 |
| 5 |
(可选)通过 ThresholdSensor + ReadingTransform 显示实际电压 |
| 6 |
使用 busctl 或 mdbctl 调试验证通信流程 |
结论:您无需手动操作 i2ctransfer,只需按上述方式在 CSR 中配置 Accessor_WriteThenRead 类型的 Scanner,即可实现“自动选通通道 + 读取数据”的完整流程。
如有进一步问题,欢迎提供 ADC 芯片型号,可协助生成更精确的系数与映射公式。
相关链接:
- ADC配置问题
- 使用Scanner读取Adc芯片数据与实际不符
- 配置Adc bus时候的问题
- 板载网卡"Type": "NICCard"如何挂到EXU设备下,并成功被发现
- 传感器适配指南 | 文档中心 | openUBMC