http://www.ithao123.cn/content-848618.html
相关代码在资源中下载。
用到的结构及,函数及其他:
/*用于产生一个等待队列的头文件,定义在wait.h中*/
#define DECLARE_WAIT_QUEUE_HEAD(name)
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
/*pin;所要获取的引脚*/
unsigned int s3c2410_gpio_getpin(unsigned int pin);
/*用于中断唤醒的,x:等待队列的头文件*/
#define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)
/*休眠,直到条件满足,wq:等待队列的头文件,condition:条件为真时,会被唤醒,假时休眠,
*在中断处理函数时,condition复制为1
*/
#define wait_event_interruptible(wq, condition)
( {
int __ret = 0;
if (!(condition))
__wait_event_interruptible(wq, condition, __ret);
__ret;
})
驱动程序:
#include <linux/module.h>
#include <linux/kernel.h>#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/irqs.h>
#include <mach/regs-gpio.h>
/*不同的linux内核,头文件会有所不同*/
static unsigned long major;
static struct class *second_key_class;
static struct device *second_key_device;
static volatile int en_press = 0;
static int key_val;
/*产生一个等待队列的头文件*/
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);/*定义一个引脚描述结构体*/
struct pindec{
unsigned long pin;
unsigned long val;
};
/*松开按键的值为0x01,0x02,0x3,0x04*/
/*按下按键时值为0x81,0x82,0x83,0x84*/
struct pindec pin_dec[4] = {
{S3C2410_GPF0,0x04},
{S3C2410_GPF1,0x01},
{S3C2410_GPF2,0x03},
{S3C2410_GPF4,0x02},
};
/*中断处理函数*/
static irqreturn_t buttons_irq(int irq,void *dev_id)
{
struct pindec *pindesc = (struct pindec *)dev_id;
/*获得引脚状态*/
unsigned long pinval = s3c2410_gpio_getpin(pindesc->pin);
/*如何按下按键,pinval =0,*/
if(pinval)key_val = pindesc->val;
else
key_val = pindesc->val|0x80;
en_press = 1;
/*唤醒中断*/
wake_up_interruptible(&button_waitq);return IRQ_RETVAL(IRQ_HANDLED);
}
static int second_key_open(struct inode *inode, struct file *file)
{
/*注册中断*/
request_irq(IRQ_EINT1,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s1",&pin_dec[1]);
request_irq(IRQ_EINT4,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s2",&pin_dec[3]);
request_irq(IRQ_EINT2,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s3",&pin_dec[2]);
request_irq(IRQ_EINT0,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s4",&pin_dec[0]);
return 0;
}
static int second_key_close(struct inode *inode, struct file *file)
{
/*释放定义的request_irq*/
free_irq(IRQ_EINT1,&pin_dec[1]);free_irq(IRQ_EINT4,&pin_dec[3]);
free_irq(IRQ_EINT2,&pin_dec[2]);
free_irq(IRQ_EINT0,&pin_dec[0]);
return 0;
}
static ssize_t second_key_read(struct file *file, char __user *user_buffer,
size_t count, loff_t *ppos)
{
if(count != 1)
return -EINVAL;
/*松开按键时,进入休眠,当中断发生时,调用中断处理函数进行唤醒*/
wait_event_interruptible(button_waitq,en_press);
/*按下按键时,传数据给用户空间*/
copy_to_user(user_buffer,&key_val,1);
en_press = 0;
return 1;
}
/*定义一个file_operations结构*/
static struct file_operations secong_key_fops {
.owner = THIS_MODULE,
.open = second_key_open,.read = second_key_read,
.release = second_key_close,
};
/*入口函数*/
static int second_key_init(void)
{
/*注册*/
major = register_chrdev(0,"second_buttons",&secong_key_fops);
/*创建类*/
second_key_class = class_create(THIS_MODULE,"second_class");
/*创建设备*/
second_key_device =
device_create(second_key_class,NULL,MKDEV(major,0),NULL,"second_device");
return 0;
}
/*出口函数*/
static void second_key_exit(void)
{
/*注销*/
unregister_chrdev(major,"second_buttons");
/*注销设备*/
device_unregister(second_key_device);
/*销毁定义的类*/
class_destroy(second_key_class);}
/*修饰*/
module_init(second_key_init);module_exit(second_key_exit);
MODULE_LICENSE("GPL");
测试程序:
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
void main(int argc,char **argv)
{
unsigned long key_val;
int fd;
fd = open("/dev/second_device",O_RDWR);
if(fd < 0)
printf("can't open!");
while(1)
{
read(fd,&key_val,1);
printf("key_val = 0x%xn",key_val);
}
}
测试就很简单了:
1.加载驱动程序:
2.执行应用程序;