我是靠谱客的博主 无情羊,这篇文章主要介绍中断程序之 --定时器使用按键去抖动引入定时器用法,现在分享给大家,希望可以做个参考。

按键去抖动引入定时器用法

定时器:定时器使用|
步骤:

  • 定义一个定时器              struct timer_list buttons_timer;
  • 初始化定时器                  init_timer(&buttons_timer);
  • 设置定时器                      buttons_timer.function = xxx  ;  buttons_timer.data = xxx;
  • 注册到内核启动定时器   add_timer(&buttons_timer);

举例说明:

jiffies  : 全局变量, 表示系统时钟滴答, 增加1 表示  系统时钟+1; 时间上一个系统滴答 10ms

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
struct pin_desc * temp_pin_des =null; static DECLARE_MUTEX(sem_button_lock); //定义互斥锁 static struct class *six_drvdrv_class; static struct class_device *six_drvdrv_class_dev; volatile unsigned long *gpfcon; volatile unsigned long *gpfdat; volatile unsigned long *gpgcon; volatile unsigned long *gpgdat; static struct timer_list button_timer; //定义一个定时器 static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* 中断事件标志, 中断服务程序将它置1,six_drv_drv_read将它清0 */ static volatile int ev_press = 0; static struct fasync_struct *button_async; struct pin_desc{ unsigned int pin; unsigned int key_val; }; /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */ /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */ static unsigned char key_val; struct pin_desc pins_desc[4] = { {S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03}, {S3C2410_GPG11, 0x04}, }; /* * 确定按键值 */ static irqreturn_t buttons_irq(int irq, void *dev_id) { temp_pin_des = (struct pin_desc *)dev_id; mod_timer(&buttons_timer, jiffies + HZ/100); //修改定时器 jiffies增长1 代表系统时钟增加1 一个系统时钟是10ms return IRQ_RETVAL(IRQ_HANDLED); } static void buttons_timeout(unsigned long data) { struct pin_desc * pindesc = temp_pin_des; unsigned int pinval; pinval = s3c2410_gpio_getpin(pindesc->pin); if (pinval) { /* 松开 */ key_val = 0x80 | pindesc->key_val; } else { /* 按下 */ key_val = pindesc->key_val; } ev_press = 1; /* 表示中断发生了 */ wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ /* 异步通知 */ kill_fasync (&button_async, SIGIO, POLL_IN); } static int six_drv_drv_open(struct inode *inode, struct file *file) { init_timer(&buttons_timer); //初始化定时器 //buttons_timer.expires = jiffies +HZ; buttons_timer.function = buttons_timeout; // 设置定时器处理函数 add_timer(&buttons_timer); //注册到内核 //非阻塞 if (file->f_flags& O_NONBLOCK) { down_trylock(&sem_button_lock); }else //阻塞 { /* 获取信号量 */ down(&sem_button_lock); } /* 注册中断 */ request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]); request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S3", &pins_desc[1]); request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", &pins_desc[2]); request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", &pins_desc[3]); return 0; } ssize_t six_drv_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { if (size != 1) return -EINVAL; if(file->f_flags & O_NONBLOCK) { if(ev_press !=1) { return -EBUSY; } }else { /* 如果没有按键动作, 休眠 */ wait_event_interruptible(button_waitq, ev_press); } /* 如果有按键动作, 返回键值 */ copy_to_user(buf, &key_val, 1); ev_press = 0; return 1; } int six_drv_drv_close(struct inode *inode, struct file *file) { /* 释放中断 */ free_irq(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2]); free_irq(IRQ_EINT19, &pins_desc[3]); up(&sem_button_lock); return 0; } static unsigned six_drv_drv_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; poll_wait(file, &button_waitq, wait); // 不会立即休眠 if (ev_press) mask |= POLLIN | POLLRDNORM; return mask; } static int six_drv_drv_fasync (int fd, struct file *filp, int on) { printk("driver: six_drv_drv_fasyncn"); return fasync_helper (fd, filp, on, &button_async); } static struct file_operations sencod_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = six_drv_drv_open, .read = six_drv_drv_read, .release = six_drv_drv_close, .poll = six_drv_drv_poll, .fasync = six_drv_drv_fasync, }; int major; static int six_drv_drv_init(void) { major = register_chrdev(0, "six_drv_drv", &sencod_drv_fops); six_drvdrv_class = class_create(THIS_MODULE, "six_drv_drv"); six_drvdrv_class_dev = class_device_create(six_drvdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */ gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); gpfdat = gpfcon + 1; gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16); gpgdat = gpgcon + 1; return 0; } static void six_drv_drv_exit(void) { unregister_chrdev(major, "six_drv_drv"); class_device_unregister(six_drvdrv_class_dev); class_destroy(six_drvdrv_class); iounmap(gpfcon); iounmap(gpgcon); return 0; } module_init(six_drv_drv_init); module_exit(six_drv_drv_exit); MODULE_LICENSE("GPL");

 

 

 

最后

以上就是无情羊最近收集整理的关于中断程序之 --定时器使用按键去抖动引入定时器用法的全部内容,更多相关中断程序之内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(97)

评论列表共有 0 条评论

立即
投稿
返回
顶部