本文共 5170 字,大约阅读时间需要 17 分钟。
#DTS配置
-
#配置DTS节点
#驱动文件中匹配 DTS 节点
#驱动说明
-
#获取ADC通道
#获取ADC值
#计算采集到的电压
#接口说明
#调试方法
-
#节点ADC值
RK3399开发板上的 AD 接口有两种,分别为:温度传感器 (Temperature Sensor)、逐次逼近ADC (Successive Approximation Register)。
TS-ADC(Temperature Sensor):支持两通道,时钟频率必须低于800KHZ
AR-ADC(Successive Approximation Register):支持六通道单端10位的SAR-ADC,时钟频率必须小于13MHZ。内核采用工业 I/O 子系统来控制 ADC,该子系统主要为 AD 转换或者 DA 转换的传感器设计。下面以SAR-ADC为例子,介绍 ADC 的基本配置方法。
#DTS配置
#配置DTS节点
SAR-ADC 的 DTS 节点在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 文件中定义,如下所示:
saradc: saradc@ff100000 { compatible = "rockchip,rk3399-saradc"; reg = <0x0 0xff100000 0x0 0x100>; interrupts =; #io-channel-cells = <1>; clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>; clock-names = "saradc", "apb_pclk"; resets = <&cru SRST_P_SARADC>; reset-names = "saradc-apb"; status = "disabled"; };
用户首先需在DTS文件中添加ADC的资源描述:
&rk_key { compatible = "rockchip,key"; status = "okay"; io-channels = <&saradc 1>; vol-up-key { linux,code = <114>; label = "volume up"; rockchip,adc_value = <1>; }; vol-down-key { linux,code = <115>; label = "volume down"; rockchip,adc_value = <170>; }; power-key { gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; linux,code = <116>; label = "power"; gpio-key,wakeup; }; menu-key { linux,code = <59>; label = "menu"; rockchip,adc_value = <746>; }; home-key { linux,code = <102>; label = "home"; rockchip,adc_value = <355>; }; back-key { linux,code = <158>; label = "back"; rockchip,adc_value = <560>; }; camera-key { linux,code = <212>; label = "camera"; rockchip,adc_value = <450>; };};
这里申请的是SARADC通道1
#驱动文件中匹配 DTS 节点
驱动key:drivers/input/keyboard/rk_keys.c 首先在驱动文件中定义 of_device_id 结构体数组:
static const struct of_device_id rk_key_match[] = { { .compatible = "rockchip,key", .data = NULL}, {},};
然后将该结构体数组填充到 platform_driver 中:
static struct platform_driver keys_device_driver = { .probe = keys_probe, .remove = keys_remove, .driver = { .name = "rk-keypad", .owner = THIS_MODULE, .of_match_table = rk_key_match,#ifdef CONFIG_PM .pm = &keys_pm_ops,#endif }};
接着在keys_probe中使用work 进行polling :
/* adc polling work */ if (ddata->chan) { INIT_DELAYED_WORK(&ddata->adc_poll_work, adc_key_poll); schedule_delayed_work(&ddata->adc_poll_work, ┊ ┊ ADC_SAMPLE_JIFFIES); }
ADC key Poll DTS资源解析
static void adc_key_poll(struct work_struct *work){ struct rk_keys_drvdata *ddata; int i, result = -1; ddata = container_of(work, struct rk_keys_drvdata, adc_poll_work.work); if (!ddata->in_suspend) { result = rk_key_adc_iio_read(ddata);/**读取SARADC值*/ if (result > INVALID_ADVALUE && ┊ result < (EMPTY_DEFAULT_ADVALUE - ddata->drift_advalue)) ddata->result = result; for (i = 0; i < ddata->nbuttons; i++) { struct rk_keys_button *button = &ddata->button[i]; if (!button->adc_value) continue; if (result < button->adc_value + ddata->drift_advalue && ┊ result > button->adc_value - ddata->drift_advalue) button->adc_state = 1; else button->adc_state = 0; if (button->state != button->adc_state) mod_timer(&button->timer, ┊ jiffies + DEBOUNCE_JIFFIES); } } schedule_delayed_work(&ddata->adc_poll_work, ADC_SAMPLE_JIFFIES);}
#驱动说明
#获取ADC通道
在解析资源DTS时 获取对应的通道 struct iio_channel *chan; /定义 IIO 通道结构体chan = iio_channel_get(&pdev->dev, NULL); /获取 IIO 通道结构体/
static int rk_keys_parse_dt(struct rk_keys_drvdata *pdata,struct platform_device *pdev){ struct device_node *node = pdev->dev.of_node; struct device_node *child_node; struct iio_channel *chan; int ret, gpio, i = 0; u32 code, adc_value, flags, drift; if (of_property_read_u32(node, "adc-drift", &drift)) pdata->drift_advalue = DRIFT_DEFAULT_ADVALUE; else pdata->drift_advalue = (int)drift; chan = iio_channel_get(&pdev->dev, NULL);...............
#获取ADC值
在adc_key polling中 调用 iio_read_channel_raw 函数读取 AD 采集的原始数据并存入 val 中
ret = iio_read_channel_raw(channel, &val);
#计算采集到的电压
Vref / (2^n-1) = Vresult / raw
注:
Vref 为标准电压 n 为 AD 转换的位数 Vresult 为用户所需要的采集电压 raw 为 AD 采集的原始数据
#接口说明
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:存放读取结果的指针
#调试方法
#节点ADC值
cat /sys/bus/iio/devices/iio\:device1/in_voltage*_raw8761021164512513349
回复「 篮球的大肚子」进入技术群聊
回复「1024」获取1000G学习资料
转载地址:https://linus.blog.csdn.net/article/details/105153976 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!