linux4.6 EC11旋转编码器的驱动

最近项目使用了旋转编码器EC11,遍查内核,发现并没有它的驱动,查了查CSDN,终于找到一篇有用的。根据自己的需要和对最基础的gpio_key.c的理解,我改写出了一份EC11的专用驱动。

感谢下面博主的启发,有了这位高人的指点,我才有信心改写成功。并决定向他学习,将自己成功的代码与大家分享。

https://blog.csdn.net/aifei7320/article/details/50037689

1.了解ec11旋转编码器

参考链接:https://www.yiboard.com/thread-1001-1-1.htmlhttps://www.jianshu.com/p/41fa67ecb248

网上相关的介绍很多,读完以上内容,我对自己使用的产品有了基本的认识:

首先,知道它电路的连接使用,参考说明书上面的电路图。该连电阻连电阻,该接电容接电容,才能正确出波形。

接着,知道它是一定位一脉冲式,通过示波器观察到转动一格,A、B都有完整的脉冲产生。(两定位的驱动没有想)

最后,顺时钟转的波形和逆时钟转的波形。

关于一圈多少格,个人认为,如果说转够一圈有什么特殊波形的话,这个可以留意一下,但是我产品没有,此特性忽略。

此处应该有图

2.分析驱动实现

有了上述不同旋转方向的波形的图片以后,开始思考实现驱动的方案和效果,先初步想一下,然后再参考别人的linux代码、C语言代码进行补充修正。

2.1  驱动的方案

提供的方案有以下

1)记录信号A、B两个的下降沿(或上升沿)出现的时间,然后相减的正负结果,暴露出A与B谁先出现,从而知道是左旋还是右旋。

要点:A与B的中断都要关注,全局变量记录中断出现时间。

2)以其中一个信号作为时钟线(中断线),以上升沿(或下降沿)中断触发,读取另外一根(信号线)的电平状态,从而知左旋还是右旋。

要点:A与B仅选择关注一个中断,不需要全局变量记录。

因为驱动基于gpio_key.c,它是中断发送然后检测电平的方式。参考了其他博主,都是第二种方式,有成功的例子,所以采用了第二种方式。

另外这里考虑另外一个问题,那就是按钮值的处理。有的ec11除了左旋、右旋还可以像普通按钮按下,也就是它有3个值。我研究了手头有按钮功能的按键,发现按钮事件对A、B信号影响不大,它另外通过引脚C输出,波形表现是平时高电平,按键按下变成低,松开又成高。所以按钮事件交给驱动gpio_key.c处理就好,不予关注。而左旋、右旋事件交给驱动gpio_ec11.c(在gpio_key.c基础上修改而成,不影响gpio_key.c驱动)。参考我后面的设备树描述,这个就好懂了。

总结一下要做的工作就是在上,改写出旋转功能(这个驱动不负责按钮部分所以不是旋转按钮)的驱动gpio_ec11.c。

2.2  预计效果

最后驱动要实现的功能是,左旋的时候,输出一个按键值。右旋的时候,输出另外一个按键值。

怎么说呢,效果就是左旋一格相当于按键A完成一次按下松开动作,右旋一格相当于按键B完成一次按下松开动作。

3.驱动编辑

因为修改部分多,而且很多变量类型修改的细节,这里仅展示重点讲解,详情参考提供的源代码

3.1 相关头文件

因为不能影响到gpio_key.c,所以需要创建新的结构体数据。按照参考链接1博主的做法,在struct gpio_keys_button 中增加成员,并修改变量类型。

gpio_ec11.h ——修改自gpio_key.h

修改部分:

#ifndef _GPIO_EC11_H
#define _GPIO_EC11_H

……

struct gpio_ec11_button {  /*重要结构体名字换掉*/
    unsigned int code;  /*没有用到,为了适应旧架构就保留没删除*/
    unsigned int leftcode;  /*记录左旋键值*/
    unsigned int rightcode;  /*记录右旋键值*/
    int gpio;  /*旋转编码器A引脚的gpio号*/
    int subgpio;  /*旋转编码器B引脚的gpio号*/

 ……

};

/*原来struct gpio_keys_button部分都相应改成struct gpio_ec11_button,为减少工作量,变量名不变*/

struct gpio_ec11_platform_data {
    struct gpio_ec11_button *buttons; 

 ……

};

总结,这样修改的主要是保证改的新驱动不会影响就驱动的使用,没换变量名是为了尽可能少改。

3.2 相关源文件

既然要修改源文件,那就得先把基础文件gpio_key.c理解清楚。

采用了最笨的办法,就是在里面的主要功能函数里,首加“printk("%s start\n",__FUNCTION__);”,“尾加printk("%s end\n",__FUNCTION__);” ,再配合按键的使用观察内核打印信息,基本摸清楚驱动调用顺序。最后,搜几篇gpio_key.c驱动详解之类的文章,对每个功能函数加深了解,最后着手改程序。我觉得高手可能直接看代码能理清,emmm~反正我不行,不管什么手段办法,摸清楚原来的框架是必须的。

gpio_ec11.c ——修改自gpio_key.c

…… //25h

#include <linux/gpio_ec11.h>  //20190408替换成改的头文件

…… //35h

struct gpio_ec11_data {
    const struct gpio_ec11_button *button;  //20190408
 ……
};

struct gpio_ec11_drvd

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
在 gpio-keyc的基础上改写的旋转按钮 ec11的驱动,已经经过了测试。可自定义左旋和右旋的键值。如果按键值输入是第三个引脚,也支持按键操作 补存的头文件: gpio_ec11.h #ifndef _GPIO_EC11_H #define _GPIO_EC11_H struct device; struct gpio_desc; /** * struct gpio_ec11_button - configuration parameters * @leftcode: ec11 left direction input event code (KEY_*, SW_*) * @rightcode: ec11 right direction input event code (KEY_*, SW_*) * @gpio: %-1 if this key does not support gpio * @gpio: %-1 if this key does not support gpio * @active_low: %true indicates that button is considered * depressed when gpio is low * @desc: label that will be attached to button's gpio * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS) * @wakeup: configure the button as a wake-up source * @debounce_interval: debounce ticks interval in msecs * @can_disable: %true indicates that userspace is allowed to * disable button via sysfs * @value: axis value for %EV_ABS * @irq: Irq number in case of interrupt keys * @gpiod: GPIO descriptor */ struct gpio_ec11_button { unsigned int code; unsigned int leftcode; /*记录左旋键值*/ unsigned int rightcode; /*记录右旋键值*/ int gpio; /*旋转编码器A引脚的gpio号*/ int subgpio; /*旋转编码器B引脚的gpio号*/ int active_low; const char *desc; unsigned int type; int wakeup; int debounce_interval; bool can_disable; int value; unsigned int irq; unsigned int irq_flags; struct gpio_desc *gpiod; }; /** * struct gpio_ec11_platform_data - platform data for gpio_ec11 driver * @buttons: pointer to array of &gpio;_keys_button structures * describing buttons attached to the device * @nbuttons: number of elements in @buttons array * @poll_interval: polling interval in msecs - for polling driver only * @rep: enable input subsystem auto repeat * @enable: platform hook for enabling the device * @disable: platform hook for disabling the device * @name: input device name */ struct gpio_ec11_platform_data { struct gpio_ec11_button *buttons; int nbuttons; unsigned int poll_interval; unsigned int rep:1; int (*enable)(
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值