14. 旋转编码器 - 用于 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)
14.2. 事件 / 状态机¶
在半周期模式下,使用上面的状态 a) 和 c) 基于上一个稳定状态来确定旋转方向。如果在状态 b) 和 d) 中新的稳定状态与上一个状态不同(即旋转没有在半途中反向),则报告事件。
否则,适用以下情况
- 通道 A 上升沿,通道 B 处于低电平状态
此状态用于识别顺时针转动
- 通道 B 上升沿,通道 A 处于高电平状态
进入此状态时,编码器被置于“已准备”状态,这意味着它已经看到一步过渡的一半。
- 通道 A 下降沿,通道 B 处于高电平状态
此状态用于识别逆时针转动
- 通道 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);
...
请查阅设备树绑定文档以查看驱动程序支持的所有属性。