RK 利用SARADC 来做多个按键
发布日期:2021-06-30 18:44:44 浏览次数:3 分类:技术文章

本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:对比一段ADC键值读取的代码
下一篇:你知道用git打补丁吗?

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月23日 20时45分06秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

Oracle 作业记录 2019-04-30
putty连接AWS配置(multimedia project) 2019-04-30
Hourglass Network 沙漏网络 (pose estimation姿态估计) 2019-04-30
OpenCV实战(二)——答题卡识别判卷 2019-04-30
目标检测神经网络的发展历程(52 个目标检测模型) 2019-04-30
Boundary loss 损失函数 2019-04-30
神经网络调参实战(一)—— 训练更多次数 & tensorboard & finetune 2019-04-30
tensorflow使用tensorboard进行可视化 2019-04-30
神经网络调参实战(二)—— activation & initializer & optimizer 2019-04-30
凸优化 convex optimization 2019-04-30
数据库索引 & 为什么要对数据库建立索引 / 数据库建立索引为什么会加快查询速度 2019-04-30
IEEE与APA引用格式 2019-04-30
research gap 2019-04-30
pytorch训练cifar10数据集查看各个种类图片的准确率 2019-04-30
Python鼠标点击图片,获取点击点的像素坐标 2019-04-30
路径规划(一) —— 环境描述(Grid Map & Feature Map) & 全局路径规划(最优路径规划(Dijkstra&A*star) & 概率路径规划(PRM&RRT)) 2019-04-30
神经网络调参实战(四)—— 加深网络层次 & 批归一化 batch normalization 2019-04-30
数据挖掘与数据分析(三)—— 探索性数据分析EDA(多因子与复合分析) & 可视化(1)—— 假设检验(μ&卡方检验&方差检验(F检验))&相关系数(皮尔逊&斯皮尔曼) 2019-04-30
RRT算法(快速拓展随机树)的Python实现 2019-04-30
路径规划(二) —— 轨迹优化(样条法) & 局部规划(人工势能场法) & 智能路径规划(生物启发(蚁群&RVO) & 强化学习) 2019-04-30