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);

...

請查閱裝置樹繫結文件以檢視驅動程式支援的所有屬性。