android 按键.docx
- 文档编号:9237213
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:28
- 大小:909.37KB
android 按键.docx
《android 按键.docx》由会员分享,可在线阅读,更多相关《android 按键.docx(28页珍藏版)》请在冰豆网上搜索。
android按键
android物理按键
关键词:
android 按键 矩阵按键AD按键
平台信息:
内核:
linux2.6/linux3.0
系统:
android/android4.0
平台:
S5PV310(samsungexynos4210)
一、硬件部分:
1、矩阵按键、IO按键、AD按键
这个知识相对来说比较简单,不过上次真有一个网友不太清楚这个。
所以这个基础部分我们在这里也说一下。
(1)、矩阵按键
记得上大学时学单片机时,这个矩阵按键还是个重点呢,上面的图还是AT89S52的片子,工作原理比较简单,通过行、列来确定是那个按键按下,比如说上图标号为1的键按下,IO(P1.7,P1.3)有电平变化,程序可以通过这里来判断是那一个键按下的,同理标号为2的按键按下IO(P1.4,P1.0)有电平变化。
这样做程序上要从两个IO来判断是那个键按下,多了一个步骤,但是在硬件上有一个优势,就是如果按键比较多的时候比较节省IO口,比如说上面4x4=16,8个IO可以做16个按键,8x8=64,16个IO可以做64个按键。
优点:
可以用少的IO来做多个按键,判断按键比较准确;
缺点:
程序上相对IO按键来说多了一步。
(2)、IO按键
这个就比较简单了,用一个IO口的高低电平来判断按键是否按下。
优点:
程序、硬件电路都比较简单,判断按键比较准确;
缺点:
IO有限、按键多时不太合适。
比如矩阵按键16个IO可以表示64个按键,IO的话只有16个。
(3)、AD按键
这个在之前在做电视的时候用的比较多一点。
AD按键就是通过一个ADC接口,如下图所示,给一个VCC电压,比如说S1接地时AD接口得到的模拟电压值为ADC=0;当S2按下时,ADC= VCC/(R1+R2)*R2;这样就可以得到不同的ADC值,程序中在这里判断是那个按键按下。
优点:
程序、硬件电路都比较简单,一个IO可以做多个按键;
缺点:
AD按键有时候判断不准确,所以在程序中要多加检测AD值的次数。
2、S5PV310的矩阵按键
硬件原理图如下:
硬件接口说明:
vol+,vol-,back,home,menu为1*5的矩阵键盘,芯片接口信息如下:
行
XGNSS_GPIO_3/KP_COL3
XGNSS_GPIO_4/KP_COL4
XGNSS_GPIO_5/KP_COL5
XGNSS_GPIO_6/KP_COL6
XGNSS_GPIO_7/KP_COL7
列
XEINT17/KP_ROW1
我们这里1*5=5也没有节省多少IO呀?
情况是这样的,我们的原理图是从三星开发板上参考过来的,开发板上按键本来多一点,可是我们用不了那么多,人家那样做比较合理。
可是我们“偷懒”,硬件上不用改,软件上也不用改,从这一点也可以看出我们国内做技术这个行业的有点……不太深入呀,整天老板在催,可是我们在细节上做不太好呀。
三星在IO矩阵也有专用接口,所以就“奢侈”一次,用1*5的矩阵来实现5个按键。
3、S5PV310的矩阵按键接口
看一下芯片上的专用接口,如下图,全用的话有点多。
关于专用接口的寄存器,这些寄存器我们后面要用得到的,按键的行、列信息会在这里面暂存的。
以S5PV310为例,驱动代码:
samsung-keypad.c
软件部分:
总体流程图如下,这个是在触摸屏基础上改过来的,感觉流程都是这个样子的。
中断触发,中断处理。
一、矩阵键行、列设定,和上报键值设定
在android-kernel-samsung-dev/arch/arm/mach-exynos/mach-smdkv310.c中
[cpp] viewplaincopy
1.static uint32_t smdkv310_keymap[] __initdata = {
2. /* KEY(row, col, keycode) */
3. KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
4. KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
5. KEY(1, 3, KEY_A), KEY(1, 4, KEY_C), KEY(1, 5, KEY_E),
6. KEY(1, 6, KEY_B), KEY(1, 7, KEY_D)//
(1)、键值初始化;
7.};
8.
9.static struct matrix_keymap_data smdkv310_keymap_data __initdata = {
10. .keymap = smdkv310_keymap,
11. .keymap_size = ARRAY_SIZE(smdkv310_keymap),
12.};
13.static struct samsung_keypad_platdata smdkv310_keypad_data __initdata = {
14. .keymap_data = &smdkv310_keymap_data,
15. .rows = 2, //
(2)、行、列设定,8行、2列,其实我们只用了5行、1列;
16. .cols = 8,
17.};
18.static void __init smdkv310_machine_init(void)
19.{
20. samsung_keypad_set_platdata(&smdkv310_keypad_data); //(3)、平台设备初始化;
21.}
(1)、KEY(row,col,keycode)
KEY这个宏在android-kernel-samsung-dev/include/linux/input/Matrix_keypad.h中实现:
[cpp] viewplaincopy
1.#define MATRIX_MAX_ROWS 32
2.#define MATRIX_MAX_COLS 32
3.#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
4. (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
5. ((val) & 0xffff))
keycode的值在android-kernel-samsung-dev/include/linux/input.h中有定义,如下:
[cpp] viewplaincopy
1.#define KEY_RESERVED 0
2.#define KEY_ESC 1
3.#define KEY_1 2
4.#define KEY_2 3
5.#define KEY_3 4
6.#define KEY_4 5
7.#define KEY_5 6
8.#define KEY_6 7
9.#define KEY_7 8
10.#define KEY_8 9
11.#define KEY_9 10
12.#define KEY_0 11
13.#define KEY_MINUS 12
14.#define KEY_EQUAL 13
15.#define KEY_BACKSPACE 14
16.#define KEY_TAB 15
17.#define KEY_Q 16
18.#define KEY_W 17
19.#define KEY_E 18
20.#define KEY_R 19
21.#define KEY_T 20
22.#define KEY_Y 21
23.#define KEY_U 22
(2)、行列设定;
[cpp] viewplaincopy
1..rows = 2,
2..cols = 8,
(3)、平台设备初始化;
[cpp] viewplaincopy
1.samsung_keypad_set_platdata(&smdkv310_keypad_data)。
二、上面设定的keycode键值和上层相对应
4.0.3_r1/device/samsung/smdkv310/samsung-keypad.kl中
[cpp] viewplaincopy
1.key 2 DPAD_UP WAKE_DROPPED
2.key 3 DPAD_CENTER WAKE_DROPPED
3.key 4 DPAD_DOWN WAKE_DROPPED
4.key 5 DPAD_RIGHT WAKE_DROPPED
5.key 6 DPAD_LEFT WAKE_DROPPED
6.key 18 VOLUME_DOWN WAKE
7.key 30 HOME WAKE_DROPPED
8.key 32 MENU WAKE_DROPPED
9.key 46 VOLUME_UP WAKE
10.key 48 BACK WAKE_DROPPED
11.key 10 POWER WAKE
总体对应图:
以KEY_A为例,KEY_A30最终和上层的keypad.kl中的30HOME相对应
三、矩阵键盘驱动程序分析
android-kernel-samsung-dev/drivers/input/keyboard/samsung-keypad.c
1、probe函数分析:
[cpp] viewplaincopy
1.static int __devinit samsung_keypad_probe(struct platform_device *pdev)
2.{
3. const struct samsung_keypad_platdata *pdata;
4. const struct matrix_keymap_data *keymap_data;
5. struct samsung_keypad *keypad;
6. struct resource *res;
7. struct input_dev *input_dev;
8. unsigned int row_shift;
9. unsigned int keymap_size;
10. int error;
11. ………………
12. keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]);
13.
14. keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL);
15. input_dev = input_allocate_device();
16. if (!
keypad || !
input_dev) {
17. error = -ENOMEM;
18. goto err_free_mem;
19. }
20.
21. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
22. if (!
res) {
23. error = -ENODEV;
24. goto err_free_mem;
25. }
26.
27. keypad->base = ioremap(res->start, resource_size(res));
28. if (!
keypad->base) {
29. error = -EBUSY;
30. goto err_free_mem;
31. }
32. …………
33.//
(1)、input参数初始化;
34. keypad->input_dev = input_dev;
35. keypad->row_shift = row_shift;
36. keypad->rows = pdata->rows;
37. keypad->cols = pdata->cols;
38. init_waitqueue_head(&keypad->wait);
39.
40. input_dev->name = pdev->name;
41. input_dev->id.bustype = BUS_HOST;
42. input_dev->dev.parent = &pdev->dev;
43. input_set_drvdata(input_dev, keypad);
44.//
(2)、打开、关闭函数;
45. input_dev->open = samsung_keypad_open;
46. input_dev->close = samsung_keypad_close;
47.
48. input_dev->evbit[0] = BIT_MASK(EV_KEY);
49. if (!
pdata->no_autorepeat)
50. input_dev->evbit[0] |= BIT_MASK(EV_REP);
51.
52. input_set_capability(input_dev, EV_MSC, MSC_SCAN);
53.
54. input_dev->keycode = keypad->keycodes;
55. input_dev->keycodesize = sizeof(keypad->keycodes[0]);
56. input_dev->keycodemax = pdata->rows << row_shift;
57.
58. matrix_keypad_build_keymap(keymap_data, row_shift,
59. input_dev->keycode, input_dev->keybit);
60.
61. keypad->irq = platform_get_irq(pdev, 0);
62. if (keypad->irq < 0) {
63. error = keypad->irq;
64. goto err_put_clk;
65. }
66.//(3)、中断函数注册;
67. error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq,
68. IRQF_ONESHOT, dev_name(&pdev->dev), keypad);
69. if (error) {
70. dev_err(&pdev->dev, "failed to register keypad interrupt\n");
71. goto err_put_clk;
72. }
73.//(4)、input驱动注册。
74. error = input_register_device(keypad->input_dev);
75. if (error)
76. goto err_free_irq;
77.
78. device_init_wakeup(&pdev->dev, pdata->wakeup);
79. platform_set_drvdata(pdev, keypad);
80. return 0;
81.
82.………………
83.}
(1)、input参数初始化;
(2)、打开、关闭函数;
[cpp] viewplaincopy
1.input_dev->open = samsung_keypad_open;
2.static int samsung_keypad_open(struct input_dev *input_dev)
3.{
4. struct samsung_keypad *keypad = input_get_drvdata(input_dev);
5. samsung_keypad_start(keypad);
6. return 0;
7.}
8.其实open函数调用samsung_keypad_start()函数,对按键的寄存器一些操作,如下面寄存器列表中的。
9.static void samsung_keypad_start(struct samsung_keypad *keypad)
10.{
11. unsigned int val;
12. /* Tell IRQ thread that it may poll the device. */
13. keypad->stopped = false;
14. clk_enable(keypad->clk);
15. /* Enable interrupt bits. */
16. val = readl(keypad->base + SAMSUNG_KEYIFCON);
17. val |= SAMSUNG_KEYIFCON_INT_F_EN | SAMSUNG_KEYIFCON_INT_R_EN;
18. writel(val, keypad->base + SAMSUNG_KEYIFCON);
19. /* KEYIFCOL reg clear. */
20. writel(0, keypad->base + SAMSUNG_KEYIFCOL);
21.}
(3)、中断函数注册;
[cpp] viewplaincopy
1.error=request_threaded_irq(keypad->irq,NULL, samsung_keypad_irq,IRQF_ONESHOT, dev_name(&pdev->dev), keypad);
request_threaded_irq这个函数也许我们比较陌生,可是看下下面一个函数也许就不难理解了:
[cpp] viewplaincopy
1.static inline int __must_check
2.request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
3. const char *name, void *dev)
4.{
5. return request_threaded_irq(irq, handler, NULL, flags, name, dev);
6.}
这个函数跟中断的作用是一样的,keypad->irq=platform_get_irq(pdev,0);于中段号,当有按键按下时,会跳到中断函数,samsung_keypad_irq中;
(4)、input驱动注册,input驱动比较重要,触摸屏、按键、gsensor、battery等都是通过input子系统上报的。
2、中断函数:
samsung_keypad_irq分析,当有按键按下时,调用这个函数
[cpp] viewplaincopy
1.static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
2.{
3. struct samsung_keypad *keypad = dev_id;
4.
5. unsigned int row_state[SAMSUNG_MAX_COLS];
6. unsigned int val;
7. bool key_down;
8. do {
9. val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
10. /* Clear interrupt. */
11.//
(1)、清除中断;
12. writel(~0x0, keypad->base + SAMSUNG_KEYIFSTSCLR);
13.//
(2)、扫描行列值,写入寄存器;
14. samsung_keypad_scan(keypad, row_state);
15.//(3)、
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- android 按键