adc 使用
简介
aio-3399j 开发板上的 ad 接口有两种,分别为:温度传感器 (temperature sensor)、逐次逼近adc (successive approximation register)。其中:
ts-adc(temperature sensor):支持两通道,时钟频率必须低于800khz
sar-adc(successive approximation register):支持六通道单端10位的sar-adc,时钟频率必须小于13mhz。
内核采用工业 i/o 子系统来控制 adc,该子系统主要为 ad 转换或者 da 转换的传感器设计。 下面以sar-adc为例子,介绍 adc 的基本配置方法。
dts配置
配置dts节点
aio-3399j sar-adc 的 dts 节点在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 文件中定义,如下所示:
saradc: saradc@ff100000 { compatible = rockchip,rk3399-saradc; reg = ; interrupts = ; #io-channel-cells = ; clocks = , ; clock-names = saradc, apb_pclk; status = disabled; };
用户首先需在dts文件中添加adc的资源描述:
kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi : adc_demo: adc_demo{ status = disabled; compatible = firefly,rk3399-adc; io-channels = ; };
这里申请的是saradc通道3.
在驱动文件中匹配 dts 节点
用户驱动可参考firefly adc demo :kernel/drivers/adc/adc-firefly-demo.c,这是一个侦测firefly-rk3399风扇状态的驱动。 首先在驱动文件中定义 of_device_id 结构体数组:
static const struct of_device_id firefly_adc_match[] = { { .compatible = firefly,rk3399-adc }, {}, };
然后将该结构体数组填充到要使用 adc 的 platform_driver 中:
static struct platform_driver firefly_adc_driver = { .probe = firefly_adc_probe, .remove = firefly_adc_remove, .driver = { .name = firefly_adc, .owner = this_module, .of_match_table = firefly_adc_match, }, };
接着在firefly_adc_probe中对dts所添加的资源进行解析:
static int firefly_adc_probe(struct platform_device *pdev) { printk(firefly_adc_probe!\n); chan = iio_channel_get(&(pdev->dev), null); if (is_err(chan)){ chan = null; printk(%s() have not set adc chan\n, __function__); return -1; } fan_insert = false; if (chan) { init_delayed_work(&adc_poll_work, firefly_demo_adc_poll); schedule_delayed_work(&adc_poll_work,1000); } return 0; }
驱动说明
获取 ad 通道
struct iio_channel *chan; //定义 iio 通道结构体chan = iio_channel_get(&pdev->dev, null); //获取 iio 通道结构体
注:iio_channel_get 通过 probe 函数传进来的参数 pdev 获取 iio 通道结构体,probe 函数如下:
static int xxx_probe(struct platform_device *pdev);
读取 ad 采集到的原始数据
int val,ret; ret = iio_read_channel_raw(chan, &val);
调用 iio_read_channel_raw 函数读取 ad 采集的原始数据并存入 val 中。
计算采集到的电压
使用标准电压将 ad 转换的值转换为用户所需要的电压值。其计算公式如下:
vref / (2^n-1) = vresult / raw
注:
vref 为标准电压
n 为 ad 转换的位数
vresult 为用户所需要的采集电压
raw 为 ad 采集的原始数据
例如,标准电压为 1.8v,ad 采集位数为 10 位,ad 采集到的原始数据为 568,则:
vresult = (1800mv * 568) / 1023;
接口说明
struct iio_channel *iio_channel_get(struct device *dev, const char *consumer_channel);
功能:获取 iio 通道描述
参数:
dev: 使用该通道的设备描述指针
consumer_channel: 该设备所使用的 iio 通道描述指针
void iio_channel_release(struct iio_channel *chan);
功能:释放 iio_channel_get 函数获取到的通道
参数:
chan:要被释放的通道描述指针
int iio_read_channel_raw(struct iio_channel *chan, int *val);
功能:读取 chan 通道 ad 采集的原始数据。
参数:
chan:要读取的采集通道指针
val:存放读取结果的指针
调试方法
demo程序使用
在kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi中使能adc_demo,将”disabled” 改为 “okay”:
adc_demo: adc_demo{ status = okay; compatible = firefly,rk3399-adc; io-channels = ; };
编译内核,烧录内核到firefly-rk3399 开发板上,然后插拔风扇时,会打印内核log信息如下:
[ 85.158104] fan insert! raw= 135 voltage= 237mv [ 88.422124] fan out! raw= 709 voltage=1247mv
获取所有adc值
有个便捷的方法可以查询到每个saradc的值:
cat /sys/bus/iio/devices/iio\:device0/in_voltage*_raw
faqs
为何按上面的步骤申请saradc,会出现申请报错的情况?
驱动需要获取adc通道来使用时,需要对驱动的加载时间进行控制,必须要在saradc初始化之后。saradc是使用module_platform_driver()进行平台设备驱动注册,最终调用的是module_init()。所以用户的驱动加载函数只需使用比module_init()优先级低的,例如:late_initcall(),就能保证驱动的加载的时间比saradc初始化时间晚,可避免出错。
火星人集成灶被《向往的生活》导演组禁用,蘑菇屋一夜回到解放前
使用两个晶体管构建的迷你FM发射器电路
华为P10还未上市,华为Mate10配置就被曝出!
谷歌的智能助理Google Assistant 开启了多语言支持
最全:常见升压芯片电路设计选型及汇总
fireflyAIO-3399J主板ADC使用介绍
华为回应高通4G芯片解禁:明年手机计划照旧
一辆400多公里续航的特斯拉干翻了一切,它到底是怎么赢的
美团携配送无人机首次亮相CES
可穿戴设备八大主流芯片商实力对比
荣耀普调工资?华为手机10月暴涨93%!中国智能手机复苏步伐加速
OpenDaylight中的OSGi
iPhone XI爆料:A13仿生处理器、更大容量电池
BananaPi 开源社区完成基于Rockchip RK3588J/3588M芯片的全工规,全国产化验证
5G商用开启, 宏基站PCB市场在三年内有望达到279亿元
纳米笼催化剂保障燃料电池超长稳定运行时间
转行人工智能该怎么入手
AEIS公司推出LCM4000HV系列可配置电源
dfrobot牛眼轮 万向轮简介
ST25DV——解锁NFC芯片的多重应用场景