14. rotary-encoder - GPIO 连接设备的通用驱动程序

作者:

Daniel Mack <daniel@caiaq.de>, 2009 年 2 月

14.1. 功能

旋转编码器是使用两根线连接到 CPU 或其他外围设备的设备。 输出相移 90 度,通过触发下降沿和上升沿,可以确定旋转方向。

一些编码器在稳定状态下两个输出都为低电平,另一些编码器也具有两个输出都为高电平的稳定状态(半周期模式),而另一些编码器在所有步进中都具有稳定状态(四分之一周期模式)。

这两个输出的相位图如下所示

                _____       _____       _____
               |     |     |     |     |     |
Channel A  ____|     |_____|     |_____|     |____

               :  :  :  :  :  :  :  :  :  :  :  :
          __       _____       _____       _____
            |     |     |     |     |     |     |
Channel B   |_____|     |_____|     |_____|     |__

               :  :  :  :  :  :  :  :  :  :  :  :
Event          a  b  c  d  a  b  c  d  a  b  c  d

              |<-------->|
                one step

              |<-->|
                one step (half-period mode)

              |<>|
                one step (quarter-period mode)
更多信息,请参阅

https://en.wikipedia.org/wiki/Rotary_encoder

14.2. 事件/状态机

在半周期模式下,使用上述状态 a) 和 c) 根据最后一个稳定状态确定旋转方向。 如果新的稳定状态与上一个状态不同(即旋转没有中途反转),则在状态 b) 和 d) 中报告事件。

否则,以下适用

  1. 通道 A 上的上升沿,通道 B 处于低电平状态

    此状态用于识别顺时针旋转

  2. 通道 B 上的上升沿,通道 A 处于高电平状态

    当进入此状态时,编码器进入“准备就绪”状态,这意味着它已经看到了一步过渡的一半。

  3. 通道 A 上的下降沿,通道 B 处于高电平状态

    此状态用于识别逆时针旋转

  4. 通道 B 上的下降沿,通道 A 处于低电平状态

    停车位置。 如果编码器进入此状态,则应该发生完全过渡,除非它在中途翻转回来。“准备就绪”状态告诉我们这一点。

14.3. 平台要求

由于此驱动程序中没有硬件相关的调用,因此与其一起使用的平台必须支持 gpiolib。 另一个要求是 IRQ 必须能够在两个边沿上触发。

14.4. 板级集成

要在您的系统中使用此驱动程序,请注册一个名称为“rotary-encoder”的 platform_device,并将 IRQ 和一些特定的平台数据与其关联。 由于驱动程序使用通用设备属性,因此可以通过设备树、ACPI 或使用静态板文件来完成,如下例所示

/* board support file example */

#include <linux/input.h>
#include <linux/gpio/machine.h>
#include <linux/property.h>

#define GPIO_ROTARY_A 1
#define GPIO_ROTARY_B 2

static struct gpiod_lookup_table rotary_encoder_gpios = {
        .dev_id = "rotary-encoder.0",
        .table = {
                GPIO_LOOKUP_IDX("gpio-0",
                                GPIO_ROTARY_A, NULL, 0, GPIO_ACTIVE_LOW),
                GPIO_LOOKUP_IDX("gpio-0",
                                GPIO_ROTARY_B, NULL, 1, GPIO_ACTIVE_HIGH),
                { },
        },
};

static const struct property_entry rotary_encoder_properties[] = {
        PROPERTY_ENTRY_U32("rotary-encoder,steps-per-period", 24),
        PROPERTY_ENTRY_U32("linux,axis",                      ABS_X),
        PROPERTY_ENTRY_U32("rotary-encoder,relative_axis",    0),
        { },
};

static const struct software_node rotary_encoder_node = {
        .properties = rotary_encoder_properties,
};

static struct platform_device rotary_encoder_device = {
        .name           = "rotary-encoder",
        .id             = 0,
};

...

gpiod_add_lookup_table(&rotary_encoder_gpios);
device_add_software_node(&rotary_encoder_device.dev, &rotary_encoder_node);
platform_device_register(&rotary_encoder_device);

...

请查阅设备树绑定文档以查看驱动程序支持的所有属性。