您的位置:首页 > 运维架构 > Linux

嵌入式Linux驱动学习之路(十一)按键驱动-中断机制

2016-10-25 17:48 525 查看
轮询方式:

  和led驱动不同的是在配置IO引脚的时候,把LED的输出引脚换成输入,在read函数中向外发送io的状态。必须由应用程序不断的来查询当前IO口的状态来判断。

中断方式:

/* file name: key.c */
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <linux/fs.h>
#include <asm/arch/regs-gpio.h>
#include <linux/interrupt.h>

static struct class *key_class;     //创建类
static struct class_device *key_class_devs;   //创建类对应的设备

struct pin_desc{
unsigned int pin;
unsigned int key_val;
};
struct pin_desc pins_desc[4] = {
{S3C2410_GPF0,0X01},
{S3C2410_GPF2,0X02},
{S3C2410_GPG3,0X03},
{S3C2410_GPG11,0X04},
};
unsigned char keyvals=0;

static volatile int ev_press = 0;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);    

static irqreturn_t keys_irq(int irq, void *dev_id)
{
struct pin_desc *pindesc = (struct pin_desc *)dev_id;
unsigned int pinval;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval)
{
keyvals = pindesc->key_val|0x80;
}
else
{
keyvals = pindesc->key_val;
}
ev_press = 1;
wake_up_interruptible(&button_waitq);    //休眠唤醒
return IRQ_HANDLED;
}

int key_open(struct inode *inode, struct file *fp)
{
request_irq( IRQ_EINT0, keys_irq, IRQT_BOTHEDGE, "key2", &pins_desc[0]);    //注册终端   linux会自己配置引脚
request_irq( IRQ_EINT2, keys_irq, IRQT_BOTHEDGE, "key3", &pins_desc[1]);
request_irq( IRQ_EINT11, keys_irq, IRQT_BOTHEDGE, "key4", &pins_desc[2]);
request_irq( IRQ_EINT19, keys_irq, IRQT_BOTHEDGE, "key5", &pins_desc[3]);
return 0;
}

ssize_t key_read(struct file *fp, char __user *buff, size_t count, loff_t *offp){

if(count != 1)
{
return -EINVAL;
}
wait_event_interruptible(button_waitq,ev_press);  //休眠

copy_to_user(buff,&keyvals,1);
ev_press = 0;
return 0;
}

ssize_t key_write(struct file *fp, const char __user *buf, size_t count, loff_t *ppos){
}

int key_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]);
}

struct file_operations led_fops={
.owner = THIS_MODULE,
.open = key_open,
.write  = key_write,
.read   = key_read,
.release = key_close,
};

int major;
static int key_init(void)
{
major = register_chrdev( 0,"key_drv", &led_fops );
key_class = class_create(THIS_MODULE,"key_class");
key_class_devs = class_device_create(key_class,NULL,MKDEV(major,0),NULL,"my_keys");

printk("key install Module\n");
return 0;
}

static void key_exit(void)
{
unregister_chrdev( major, "key_drv" );
class_device_unregister(key_class_devs);
class_destroy(key_class);
printk("key Module exit\n");
}

module_init(key_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");


Makefile同led中的类似。

应用程序:

#include <stdio.h>
#include <fcntl.h>

int main()
{
int fd;
unsigned char key_val;
fd = open("/dev/my_keys",O_RDWR);
if(fd<0)
{
printf("open failed\n");
return 0;
}
while(1)
{
read(fd, &key_val,1);
printf("key:%x\n",key_val);
}
}


sd
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐