1. Neza-D1开发板上只引出一个按键,是使用的LRADC检检测按键的,想使用更多按键,可以使用板子上通过PCF8574扩展出来的IO,我画的扩展板使用了四个按键,分别为PP0,PP1,PP2,PP4

  2. 设备树配置如下 内核需要勾选 Polled input device skeleton
    gpio_keys {
    compatible = “gpio-keys”;
    pinctrl-names = “default”;
    /pinctrl-0 = <&key_pins>;/
    #address-cells = <1>;
    #size-cells = <0>;
    autorepeat;
    button@0 {
    label = “Key volume up”;
    linux,code = ;
    gpios = <&pcf8574 0 GPIO_ACTIVE_LOW>; /* PP0 /
    };

    button@1 {
    label = “Key volume down”;
    linux,code = ;
    gpios = <&pcf8574 1 GPIO_ACTIVE_LOW>; /
    PP1 /
    };

    button@2 {
    label = “Key back”;
    linux,code = ;
    gpios = <&pcf8574 2 GPIO_ACTIVE_LOW>; /
    PP2 /
    };

    button@3 {
    label = “Key enter”;
    linux,code = ;
    gpios = <&pcf8574 4 GPIO_ACTIVE_LOW>; /
    PP4 */
    };

    };

  3. 编码器接在D1的PD14 PD15 设备树如下 注意需要内核勾选<> Polled GPIO Decoder Input driver
    rotary {
    compatible = “rotary-encoder”;
    pinctrl-names = “default”;
    /pinctrl-0 = <&rotary_pins>;/
    gpios = <&pio 3 14 GPIO_ACTIVE_LOW>, <&pio 3 15 GPIO_ACTIVE_LOW>; /
    PD14, PD15 /
    linux,axis = <0>; /
    REL_X */
    rotary-encoder,encoding = “gray”;
    rotary-encoder,relative-axis;
    };
    然后在内核勾选

  4. 系统启动会有如下log

     [    0.111735] input: sunxi-keyboard as /devices/virtual/input/input0  这是板载的那个LRADC 按键
     [    1.668976] rotary-encoder soc@3000000:rotary: gray 这是旋转编码器
     [    1.675145] input: soc@3000000:rotary as /devices/platform/soc@3000000/soc@3000000:rotary/input/input1
     [    3.178668] input: soc@3000000:gpio_keys as /devices/platform/soc@3000000/soc@3000000:gpio_keys/input/input5 这是扩展出来的那4个按键
     
    
  5. 查看系统里已注册的输入设备,用这个比较清楚,ls /dev/input也可以
    # evtest
    No device specified, trying to scan all of /dev/input/event*
    Available devices:
    /dev/input/event0: sunxi-keyboard
    /dev/input/event1: soc@3000000:rotary
    /dev/input/event2: sunxi-ir
    /dev/input/event3: audiocodec sunxi Audio Jack
    /dev/input/event4: soc@3000000:gpio_keys
    /dev/input/event5: ns2009_ts

  6. 可以使用evtest或hexdump来测试按键是否正常了

  7. 在代码使用就比较简单了
    #include <errno.h>
    #include <global.h>
    #include <linux/fcntl.h>
    #include <linux/input.h>
    #include <signal.h>
    #include <stdio.h> //-std=c99 -std=gnu99
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>

    #define msleep(t) usleep((t)*1000)
    FILE *fp;
    int32_t fd_key;
    int32_t fd_encoder;
    struct input_event t;
    int main(int argc, char const *argv[])
    {

    fd_key = open(“/dev/input/event1”, O_RDONLY | O_NONBLOCK);
    if (fd_key < 0)
    {
    fprintf(stderr, “error:can not open /dev/input/event1\n”);
    return -1;
    }
    fd_encoder = open(“/dev/input/event4”, O_RDONLY | O_NONBLOCK);
    if (fd_encoder < 0)
    {
    fprintf(stderr, “error:can not open /dev/input/event4\n”);
    return -1;
    }

    while (1)
    {

    // rotary encoder
    if (read(fd_encoder, &t, sizeof(t)) == sizeof(t))
    {

    if (t.type == EV_REL)
    {
    LOG_D(“ROTARY DIR: %d->%s\n”, t.value, t.value == 1 ? “CC” : “CW”);
    rotary_encoder_handler(&u8g2, t.value);
    }
    }
    // key
    if (read(fd_key, &t, sizeof(t)) == sizeof(t))
    {
    if (t.type == EV_KEY)
    {
    switch (t.code)
    {
    case KEY_OK:
    LOG_D(“KEY_ENTER %s \n”, t.value ? “Pressed” : “Released”);
    if (t.value == 0)
    rotary_encoder_button_handler(&u8g2);
    break;
    case KEY_SELECT:
    LOG_D(“KEY_SELECT %s \n”, t.value ? “Pressed” : “Released”);
    break;
    case KEY_VOLUMEUP:
    LOG_D(“KEY_VOLUMEUP %s \n”, t.value ? “Pressed” : “Released”);
    if (t.value == 0)
    {
    rotary_encoder_handler(&u8g2, -1);
    }

    break;
    case KEY_VOLUMEDOWN:
    LOG_D(“KEY_VOLUMEDOWN %s \n”, t.value ? “Pressed” : “Released”);
    if (t.value == 0)
    {
    rotary_encoder_handler(&u8g2, 1);
    }
    break;
    default:
    break;
    }
    }
    }
    usleep(1);
    }

    return 0;
    }