接下来,我们使用IMX257的IO引脚中断+Linux输入子系统实现一个模拟键盘按键。实现的效果是,我们使用IO模拟按键L、按键S和Enter键 这三个按键。
这次我们就不再多废话了,直接上程序,大家看代码:
实验效果图:
如图所示: 我们依次按下三个按键
第一个按键 显示的键值为 38 ,也就是我们的L键
第二个按键 31 自然就是S 键
第三个按键 28 自然就是enter键
驱动代码:
1 /******************************
2 linux key_inputSystem
3 *****************************/
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15
16 #include
17
18
19 #include 'mx257_gpio.h'
20 #include 'mx25_pins.h'
21 #include 'iomux.h'
22
23 #define Driver_NAME 'key_input'
24
25 #define GPIO2_9 MX25_PIN_A23
26 #define GPIO2_10 MX25_PIN_A24
27 #define GPIO2_11 MX25_PIN_A25
28
29 //定义各个按键按下的键值
30 struct pin_desc{
31 unsigned int pin;
32 char *name;
33 unsigned int key_val;
34 };
35 //当按键按下时,键值分别为 以下值
36 struct pin_desc pins_desc[3] = {
37 {GPIO2_9, 'KEY_L_9', KEY_L},
38 {GPIO2_10, 'KEY_R_10', KEY_S},
39 {GPIO2_11, 'KEY_Enter_11', KEY_ENTER},
40 };
41
42 static struct input_dev *key_input_dev;//输入子系统设备结构体
43 static struct timer_list key_timer; //定时器结构体
44 static struct pin_desc *pin_desc_irq; //保存发生中断的引脚信息
45
46 //定时器到时函数
47 static int key_timer_function(unsigned long data){
48 struct pin_desc *pin_desc_tmp = pin_desc_irq; //发生中断的引脚信息
49 unsigned int pinval_tmp; //按键键值缓冲
50 if(!pin_desc_tmp)
51 return 0;
52 pinval_tmp = gpio_get_value(IOMUX_TO_GPIO(pin_desc_tmp->pin));//获取键值
53 if(pinval_tmp){
54 //松开 :0 按下:1
55 input_event(key_input_dev,EV_KEY,pin_desc_tmp->key_val ,0);
56 input_sync(key_input_dev); //报告完毕,通知接收者
57 }else{
58 input_event(key_input_dev,EV_KEY,pin_desc_tmp->key_val ,1);
59 input_sync(key_input_dev); //报告完毕,通知接收者
60 }
61 return 0;
62 }
63 /* 中断程序key_irq */
64 static irqreturn_t key_irq_function(int irq, void *dev_id)
65 {
66 pin_desc_irq = (struct pin_desc *)dev_id; //获取中断引脚的信息
67 mod_timer(&key_timer,jiffies+HZ/50); //开启定时器,时间20ms
68
69 return IRQ_RETVAL(IRQ_HANDLED);
70 }
71 //初始化函数
72 static int __init key_input_init(void)
73 {
74 printk('<0>nHello,this is %s module!nn',Driver_NAME);
75
76 mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);//设备引脚为GPIO模式
77 mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);//设备引脚为GPIO模式
78 mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);//设备引脚为GPIO模式
79 gpio_request(IOMUX_TO_GPIO(GPIO2_9), 'GPIO2_9');//申请IO端口使用
80 gpio_request(IOMUX_TO_GPIO(GPIO2_10), 'GPIO2_10');//申请IO端口使用
81 gpio_request(IOMUX_TO_GPIO(GPIO2_11), 'GPIO2_11');//申请IO端口使用
82 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));//设备引脚为输入
83 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));//设备引脚为输入
84 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));//设备引脚为输入
85 //设备引脚为上拉输入
86 mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PU);
87 mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PU);
88 mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PU);
89 //申请中断
90 if(request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq_function, IRQF_TRIGGER_FALLING, 'key_GPIO2_9', &pins_desc[0]))
91 return -1;
92 if(request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq_function, IRQF_TRIGGER_FALLING, 'key_GPIO2_10', &pins_desc[1]))
93 return -1;
94 if(request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq_function, IRQF_TRIGGER_FALLING, 'key_GPIO2_11', &pins_desc[2]))
95 return -1;
96
97 //input输入子系统设置
98 key_input_dev = input_allocate_device();//分配一个input_dev结构体
99 //设置能产生哪些事件
100 set_bit(EV_KEY, key_input_dev->evbit); //按键事件
101 set_bit(KEY_L, key_input_dev->keybit); // L键 按键
102 set_bit(KEY_S, key_input_dev->keybit); // S键 按键
103 set_bit(KEY_ENTER, key_input_dev->keybit); // ENTER键 按键
104 set_bit(KEY_LEFTSHIFT, key_input_dev->keybit); // LEFTSHIFT键 按键
105 //注册
106 input_register_device(key_input_dev);
107
108 init_timer(&key_timer); //初始化定时器
109 key_timer.function = &key_timer_function; //设置定时器处理函数
110 add_timer(&key_timer); //将该定时器加入内核
111
112 printk('<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !n');
113 printk('Input system initialize successfu!nn');
114 return 0;
115 }
116 //exit
117 static void __exit key_input_exit(void)
118 {
119 printk('<0>nGoodbye,%s!nn',Driver_NAME);
120 /* free gpios */
121 free_irq(IOMUX_TO_IRQ(GPIO2_9), &pins_desc[0]);
122 free_irq(IOMUX_TO_IRQ(GPIO2_10), &pins_desc[1]);
123 free_irq(IOMUX_TO_IRQ(GPIO2_11), &pins_desc[2]);
124 mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
125 mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
126 mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
127 gpio_free(IOMUX_TO_GPIO(GPIO2_9));
128 gpio_free(IOMUX_TO_GPIO(GPIO2_10));
129 gpio_free(IOMUX_TO_GPIO(GPIO2_11));
130
131 del_timer(&key_timer); //删除定时器
132 input_unregister_device(key_input_dev); //注销驱动
133 input_free_device(key_input_dev); //释放结构体内存
134 printk('Input system unregister successfu!nn');
135 }
136
137 /* 这两行指定驱动程序的初始化函数和卸载函数 */
138 module_init(key_input_init);
139 module_exit(key_input_exit);
140
141 /* 描述驱动程序的一些信息,不是必须的 */
142 MODULE_AUTHOR('Lover雪');
143 MODULE_VERSION('0.1.0');
144 MODULE_DESCRIPTION('IMX257 key Driver');
145 MODULE_LICENSE('GPL');
应用程序代码:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include 'mx257_gpio.h'
13
14
15 int main(int argc, char **argv)
16 {
17 int fd;
18 int key_value,i=0,count;
19 struct input_event ev_key;
20
21 fd = open('/dev/input/event1',O_RDWR);
22 if(fd < 0){
23 printf('can't open !!!n');
24 exit(1);
25 }
26 printf('open successful!n');
27 while(1){
28 count = read(fd,&ev_key,sizeof(struct input_event));
29 for(i = 0; i<(int)count/sizeof(struct input_event); i++){
30 if(EV_KEY == ev_key.type)
31 printf('type: %d ,code: %d ,value: %d n',ev_key.type, ev_key.code,ev_key.value);
32 if(EV_SYN == ev_key.type)
33 printf('syn eventnn');
34 }
35 }
36 close(fd);
37 return 0;
38 }