概述
http://blog.chinaunix.net/uid-20768928-id-5084287.html
这两种情况,内核中都有考虑,都在drivers/input/keyboard/ 下面。
GPIO 独立按键是 gpio_keys.c
GPIO 矩阵键盘是 matrix_keypad.c
具体也没有什么好分析的,主要就是采用platform 方式注册input 子系统,往应用层报键值。
在此基础上,添加相关的驱动,格式很固有化。直接上自己整理的模板吧。
GPIO 独立按键
点击(此处)折叠或打开
- #define SABRESD_VOLUME_UP IMX_GPIO_NR(1, 4) //得到gpio number 号
- #define SABRESD_VOLUME_DN IMX_GPIO_NR(1, 5)
- //定义宏
- #ifdefined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
- #define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce)
- {
- .gpio = gpio_num,
- .type = EV_KEY,
- .code = ev_code,
- .active_low = act_low,
- .desc = "btn " descr,
- .wakeup = wake,
- .debounce_interval = debounce,
- }
- //上面宏定义的数组
- static struct gpio_keys_button CPU_NAME_buttons[] = {
- GPIO_BUTTON(SABRESD_VOLUME_UP, KEY_VOLUMEUP, 1, "volume-up", 0, 1),
- GPIO_BUTTON(SABRESD_VOLUME_DN, KEY_VOLUMEDOWN, 1, "volume-down", 0, 1),
- GPIO_BUTTON(SABRESD_POWER_OFF, KEY_POWER, 1, "power", 1, 1),
- };
- static struct gpio_keys_platform_data CPU_NAME_button_data = {
- .buttons = CPU_NAME_buttons,
- .nbuttons = ARRAY_SIZE(CPU_NAME_buttons),
- };
- //platform device 与driver 中对应的
- static struct platform_device CPU_NAME_button_device = {
- .name = "gpio-keys",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &CPU_NAME_button_data,
- }
- };
- //注册设备的函数
- static void __init CPU_NAME_add_device_buttons(void)
- {
- platform_device_register(&CPU_NAME_button_device);
- }
- #else
- static void __init CPU_NAME_add_device_buttons(void) {}
- #endif
有些时候因不同CPU BSP 的GPIO 封装,在driver 中会出现一些问题。比如 gpio_request 可能会重复(imx287,
得到GPIO号的时候就已经request 了,太TMD超前了) 如下这段代码要屏蔽。
点击(此处)折叠或打开
- #if 0
- error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
- if (error < 0) {
- pr_err("gpio-keys: failed to request GPIO %d,"
- " error %dn", button->gpio, error);
- goto fail2;
- }
- #endif
GPIO 矩阵键盘
点击(此处)折叠或打开
- #if 1
- /*
- * Tosa Keyboard
- */
- #include <linux/input/matrix_keypad.h>
- //矩阵键盘按下时对应的键码表
- static const uint32_t tosakbd_keymap[] = {
- KEY(0, 0, KEY_1),
- KEY(0, 1, KEY_2),
- KEY(0, 2, KEY_3),
- KEY(1, 0, KEY_4),
- KEY(1, 1, KEY_5),
- KEY(1, 2, KEY_6),
- KEY(2, 0, KEY_7),
- KEY(2, 1, KEY_8),
- KEY(2, 2, KEY_9),
- KEY(3, 0, KEY_UP),
- KEY(3, 1, KEY_0),
- KEY(3, 2, KEY_DOWN),
- KEY(4, 0, KEY_BACK),
- KEY(4, 1, KEY_ENTER),
- KEY(4, 2, KEY_ESC),
- };
- static struct matrix_keymap_data tosakbd_keymap_data = {
- .keymap = tosakbd_keymap,
- .keymap_size = ARRAY_SIZE(tosakbd_keymap),
- };
- //列选 得到GPIO 口number 号
- static const int tosakbd_col_gpios[] =
- {
- // MXS_PIN_TO_GPIO( PINID_SSP0_DATA5), // 4
- MXS_PIN_TO_GPIO(PINID_LCD_D08), // 5
- MXS_PIN_TO_GPIO(PINID_LCD_D09), // 6
- MXS_PIN_TO_GPIO(PINID_LCD_D10) // 7
- };
- //行选 得到GPIO 口number 号
- static const int tosakbd_row_gpios[] =
- {
- MXS_PIN_TO_GPIO(PINID_LCD_D11), // 2
- MXS_PIN_TO_GPIO(PINID_LCD_D12), // 2
- MXS_PIN_TO_GPIO(PINID_LCD_D13), // 3
- MXS_PIN_TO_GPIO(PINID_LCD_D14), // 1
- MXS_PIN_TO_GPIO(PINID_LCD_D15) // 0
- };
- //driver 中的需要的data
- static struct matrix_keypad_platform_data CPU_NAMEkbd_pdata = {
- .keymap_data = &tosakbd_keymap_data,
- .row_gpios = tosakbd_row_gpios,
- .col_gpios = tosakbd_col_gpios,
- .num_row_gpios = ARRAY_SIZE(tosakbd_row_gpios),
- .num_col_gpios = ARRAY_SIZE(tosakbd_col_gpios),
- .col_scan_delay_us = 10,
- .debounce_ms = 10,
- .wakeup = 1,
- .active_low =0 ,
- };
- static struct platform_device CPU_NAMEkbd_device = {
- .name = "matrix-keypad",
- .id = -1,
- .dev = {
- .platform_data = &CPU_NAMEkbd_pdata,
- },
- };
- #endif
上面的两种方式,有些时候因不同CPU BSP 的GPIO 封装,在driver 中会出现一些问题。由于不同CPU GPIO口
产生中断的触发方式不同,这里出现问题的更多。
点击(此处)折叠或打开
- err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
- matrix_keypad_interrupt,
- IRQF_DISABLED |
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "matrix-keypad", keypad);
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING 很多CPU无法同时支持上升延与下降延触发。只能选择其中一个,要么FALLING ,要么RISING。
这两种方式,内核都已经封装成足够简单的方式了,用不着自己去写一个驱动,类似于填空就好了。
最后
以上就是凶狠白羊为你收集整理的LINUX GPIO独立按键 和 GPIO矩阵键盘的全部内容,希望文章能够帮你解决LINUX GPIO独立按键 和 GPIO矩阵键盘所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复