gpio键盘
1,定义gpio键盘的设备数据结构platform_device
/****************************************************************************
* GPIO Attached Keys
*/
static struct gpio_keys_button dns323_buttons[] = {
{
.code= KEY_RESTART,
.gpio= DNS323_GPIO_KEY_RESET,
.desc= "Reset Button",
.active_low= 1,
}, {
.code= KEY_POWER,
.gpio= DNS323_GPIO_KEY_POWER,
.desc= "Power Button",
.active_low= 1,
},
};
static struct gpio_keys_platform_data dns323_button_data = {
.buttons= dns323_buttons,
.nbuttons= ARRAY_SIZE(dns323_buttons),
};
static struct platform_device dns323_button_device = {
.name= "gpio-keys",
.id= -1,
.num_resources= 0,
.dev= {
.platform_data= &dns323_button_data,
},
};
2,定义gpio键盘的驱动数据结构platform_driver
static struct platform_driver gpio_keys_device_driver = {
.probe= gpio_keys_probe,
.remove= __devexit_p(gpio_keys_remove),
.driver= {
.name= "gpio-keys",
.owner= THIS_MODULE,
#ifdef CONFIG_PM
.pm= &gpio_keys_pm_ops,
#endif
}
};
3,注册平台设备
platform_device_register(&dns323_button_device);
platform_driver 和platform_device的.name= "gpio-keys",都是一样。device和driver的名字一样就回调用probe函数
gpio_keys_probe();
probe函数的具体实现
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata;
struct input_dev *input;
int i, error;
int wakeup = 0;
ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
pdata->nbuttons * sizeof(struct gpio_button_data),
GFP_KERNEL);
input = input_allocate_device();
if (!ddata || !input) {
error = -ENOMEM;
goto fail1;
}
platform_set_drvdata(pdev, ddata);
input->name = pdev->name;
input->phys = "gpio-keys/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
ddata->input = input;
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
int irq;
unsigned int type = button->type ?: EV_KEY;
bdata->input = input;
bdata->button = button;
setup_timer(&bdata->timer,
gpio_keys_timer, (unsigned long)bdata);
INIT_WORK(&bdata->work, gpio_keys_report_event);
error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
if (error < 0) {
pr_err("gpio-keys: failed to request GPIO %d,"
" error %d/n", button->gpio, error);
goto fail2;
}
error = gpio_direction_input(button->gpio);
if (error < 0) {
pr_err("gpio-keys: failed to configure input"
" direction for GPIO %d, error %d/n",
button->gpio, error);
gpio_free(button->gpio);
goto fail2;
}
irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
pr_err("gpio-keys: Unable to get irq number"
" for GPIO %d, error %d/n",
button->gpio, error);
gpio_free(button->gpio);
goto fail2;
}
error = request_irq(irq, gpio_keys_isr,
IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
bdata);
if (error) {
pr_err("gpio-keys: Unable to claim irq %d; error %d/n",
irq, error);
gpio_free(button->gpio);
goto fail2;
}
if (button->wakeup)
wakeup = 1;
input_set_capability(input, type, button->code);
}
error = input_register_device(input);
if (error) {
pr_err("gpio-keys: Unable to register input device, "
"error: %d/n", error);
goto fail2;
}
device_init_wakeup(&pdev->dev, wakeup);
return 0;
fail2:
while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
if (pdata->buttons[i].debounce_interval)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio);
}
platform_set_drvdata(pdev, NULL);
fail1:
input_free_device(input);
kfree(ddata);
return error;
}
static int __devexit gpio_keys_remove(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
struct input_dev *input = ddata->input;
int i;
device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, &ddata->data[i]);
if (pdata->buttons[i].debounce_interval)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio);
}
input_unregister_device(input);
return 0;
0,初始化工作队列INIT_WORK(&bdata->work, gpio_keys_report_event);
1,主要是分配一个input设备 input_allocate_device();
2,按键中断请求
3,设置gpio为输入,gpio_direction_input(button->gpio);
4,获取gpio的中断号 irq = gpio_to_irq(button->gpio);
5,中断申请error = request_irq(irq, gpio_keys_isr,
IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
bdata);
6,初始化是否可以唤醒
if (button->wakeup)
wakeup = 1;
7,初始化按键的类型和按键码input_set_capability(input, type, button->code);
8,注册input设备error = input_register_device(input);
9,初始化唤醒源device_init_wakeup(&pdev->dev, wakeup);
4,注册成功后,当有按键按下时就调用中断回调函数
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
struct gpio_button_data *bdata = dev_id;
struct gpio_keys_button *button = bdata->button;
BUG_ON(irq != gpio_to_irq(button->gpio));
if (button->debounce_interval)
mod_timer(&bdata->timer,
jiffies + msecs_to_jiffies(button->debounce_interval));
else
schedule_work(&bdata->work);
return IRQ_HANDLED;
}
最终执行工作队列的线程函数gpio_keys_report_event
static void gpio_keys_report_event(struct work_struct *work)
{
struct gpio_button_data *bdata =
container_of(work, struct gpio_button_data, work);
struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
input_event(input, type, button->code, !!state);
input_sync(input);
}
根据gpio的状态为按键按下还是弹开,上报按键键码的事件sendevent
分享到:
相关推荐
文中仿真源码和原理图尽可能的接近实物 实测两者差异性极小 从理论学习的角度来看,基于仿真完全可以达到学习目的 从实践的角度来看,通过简单移植和调试可将仿真转换成实物 功能概述 使用51单片机基础外设GPIO进行...
学习k60 GPIO ,了解掌握独立按键和矩阵键盘的使用方面及其原理
使用PCF8574 / PCF8574A I2C GPIO,仅使用2个Arduino引脚连接矩阵键盘-轻松快捷!
如图 8×8键盘扩展电路原理 此设计通过CPLD的GPIO扩展8×8键盘,与处理器接口仅需要7个GPIO。CPLD的6位编码输出可以代表64个按键,但是必须有一个状态表示空闲状态,因此图方案只可以实现63个按键编码。如果需要...
如图 8×8键盘扩展电路原理 此设计通过CPLD的GPIO扩展8×8键盘,与处理器接口仅需要7个GPIO。CPLD的6位编码输出可以代表64个按键,但是必须有一个状态表示空闲状态,因此图方案只可以实现63个按键编码。如果需要...
该驱动基于imx6硬件平台,linux内核版本为3.14,矩阵键盘驱动IC为...原理:max7349与cpu通过i2c通信,当有按键按下,max7349扫描到该事件,产生一个脉冲发往cpu,cpu通过GPIO中断来检测该事件。该通过i2c总线读取键值。
Driver Get Started 1 Preface 2 Declaration: 2 ...键盘原理 24 GPIO 29 触摸屏 32 显示设备 38 Camera模块 47 FMRDS模块 57 蓝牙模块 62 CMMB 67 双模双待 68 USB模块 68 GPS模块 70 红外(IrDA)模块 70
2.3.5 键盘接口基本原理与结构 2.3.6 显示接口基本原理与结构 2.3.7 触摸屏接口基本原理与结构 2.3.8 音频接口基本原理与结构 2.4 嵌入式系统总线接口 2.5 嵌入式系统网络接口 2.6 嵌入式系统电源 2.7电子电路设计...
上一篇说完了STM32库开发的引脚输出控制,这一篇对其引脚输入控制方法进行说明,引脚设置为输入功能时能够感知引脚上的电平...从图中可以看出,黑色系统板的LED由GPIOC13引脚控制,低电平点亮;按键接在GPIOA0引脚,按
17、 提供4个按键输入,用于GPIO键盘试验,其中一个兼顾外部中断试验 18、 提供4位拨码开关 19、 提供复位芯片MAX811,复位可靠,独立复位按钮可手工复位 20、 提供1 路RS-232 接口,可连接PC 进行通信 21、 提供1 ...
6~12章分别介绍GPIO的应用(键盘、LED及LCD)、定时器(含PWM)、串行外设接口SPI、Flash存储器在线编程、CAN总线、A/D转换及S12XS128其他模块等。附录给出相关资料。《嵌入式系统设计实战:基于飞思卡尔S12X微控制...
第5章介绍了嵌入式系统的GPIO、A/D转换器接口、D/A转换器接口、键盘与LE D数码管接口、LCD显示接口、触摸屏接口的基本原理、电路结构与编程方法。 第6章介绍了嵌入式系统的串行接口、I2C接口、USB接口、SPI接口、PCI...
5.4.1 键盘与LED数码管接口基本原理与结构 5.4.2 用I/O口实现键盘接口 5.4.3 采用专用芯片实现键盘及LED 接口 5.5 LCD显示接口 5.5.1 LCD显示接口原理与结构 5.5.2 S3C2410A的LCD控制器 5.5.3 LCD显示的编程实例 5.6...
23个GPIO总计 - 6个模拟输入,1个SPI端口,1个I2C端口,1个硬件串行端口和10个GPIO,其中4个具有PWM 可以驱动NeoPixels,连接传感器,伺服器等。 重置按钮,用于进入引导加载程序或重新启动程序。 对于5V版本: 5V...
8个轻触按键连接到了STM32的GPIO;MPU9250采用GY-91模块,通过I2C接口连接到STM32,MPU9250由应美盛(InvenSense)出品,是MPU6050的升级版,第二代9轴组合传感器将6轴惯性测量单元(三轴加速度计+三轴陀螺仪)和三...
MPOS机电源设计方案功能概述: 该手机移动MPOS机电源通过采用1S1P锂电池来缩小其体积...TCA8414集成了键盘扫描和GPIO扩展成一个单一的程序包,简化设计,降低BOM计数 MPOS机电源硬件设计框图: MPOS机电源电路部分截图:
5.1.6 timed gpio驱动程序 139 5.1.7 ram console驱动程序 139 5.2 wakelock和early_suspend 140 5.2.1 wakelock和early_suspend的原理 140 5.2.2 Android休眠 141 5.2.3 Android唤醒 ...
每个操作系统支持的本地USB - 可以在Arduino或CircuitPython中用作USB串行控制台,键盘/鼠标HID,甚至是用于存储Python脚本的小磁盘驱动器。 可以与Arduino IDE或CircuitPython一起使用 内置红色引脚#13 LED 内置...