免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2264 | 回复: 3
打印 上一主题 下一主题

简单按键驱动问题的请教 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-20 11:39 |只看该作者 |倒序浏览
//头文件
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
#include <linux/signal.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/sysdev.h>
#include <asm/hardware/vic.h>
#include <plat/regs-irqtype.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h>
#include <mach/irqs.h>
#include <mach/gpio-bank.h>
#include <linux/delay.h>
#include <asm/delay.h>
#include <asm/param.h>
#include <linux/io.h>
#include <linux/sysdev.h>
#include <mach/map.h>


#define DEVICE_NAME "menu_test"
//#define IRQ_NO (IRQ_EINT(16))
struct menu_dev {
    struct cdev cdev;
};
struct menu_dev *menu_devp;//设备结构体指针
int IRQ_NO;//定义中断号

//函数声明
static int  menu_major = 250;
static void menu_setup_cdev(struct menu_dev * , int );
static int menu_init(void);
static int menu_open(struct inode * , struct file *);
static int menu_release(struct inode * ,struct file *);
static void init_gpio(void);

//中断处理函数
irqreturn_t menu_interrupt(int irq, void *dev_id)
{
    printk("menu_interrupt start.....!\n");
    disable_irq_nosync(irq);//关中断
    udelay(5);//延迟5ms,消除毛刺信号
    printk("i am interrup handler\n");
    init_gpio();
    enable_irq(irq);//开中断
    printk("menu_interrupt  over.......!\n");
    return IRQ_HANDLED;
}

//初始化配置函数
static void init_gpio(void)
{
    int error;
    printk("init_gpio start....\n");
   
   error = gpio_request(S5PV210_GPH2(0),"gpio_keys");//检查gpio管脚是否被使用
    if (error < 0)
            printk("gpio-keys: failed to request GPIO %d \n", S5PV210_GPH2(0));
    else
        printk("gpio %d success!\n",S5PV210_GPH2(0));
    s3c_gpio_cfgpin(S5PV210_GPH2(0),0xf); //将管脚配置为中断模式

   IRQ_NO = gpio_to_irq(S5PV210_GPH2(0));//获取中断号,其实这个我也不太清楚,看别人的。
      if (error < 0)
            printk("gpio_to_irq: failed  %d \n", S5PV210_GPH2(0));
      else
           printk("gpio_to_irq %d success!\n",S5PV210_GPH2(0));

//配置为输出 且为低电平
    s3c_gpio_cfgpin(S5PV210_GPH3(0),S3C_GPIO_OUTPUT);//配置为输出,低电平 EINT24号管脚    参照原理图上的。
    s3c_gpio_setpin(S5PV210_GPH3(0),1);
   
    s3c_gpio_cfgpin(S5PV210_GPH3(1),S3C_GPIO_OUTPUT);//配置为输出,低电平 EINT25号管脚
    s3c_gpio_setpin(S5PV210_GPH3(1),1);   

    //设置下降沿触发
    set_irq_type(IRQ_NO,IRQ_TYPE_EDGE_FALLING);   
    printk("init_gpio successed!\n");
}

static int menu_open(struct inode *inode , struct file *filp)
{
  
    int ret;
    init_gpio();//对相关端口初始化
   
    ret = request_irq(IRQ_NO, menu_interrupt,  IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DEVICE_NAME, NULL);
    if(ret < 0){
        printk("request_irq  failer\n");
        return -EFAULT;
    }   
    else
        printk("request_irq success !\n");   
    return ret;
}
static int menu_release(struct inode *inode ,struct file *filp)
{
    printk("this is release\n");
    free_irq(IRQ_NO,NULL);
    return 0;
}



static struct file_operations menu_fops = {
    .owner = THIS_MODULE,
    .open = menu_open,
    .release = menu_release,
};
static void menu_setup_cdev(struct menu_dev *dev, int minor)
{
    int err;
    int devno = MKDEV(menu_major,minor);
    cdev_init(&dev->cdev,&menu_fops);
    dev -> cdev.owner = THIS_MODULE;
    err = cdev_add(&dev->cdev, devno, 1);
    if(err){
        printk("error  %d adding menu %d \n",err,minor);   
    }
    printk("menu_setup_cdev  over!\n");
}

static int menu_init(void)
{
    int ret = 0;
    dev_t dev = MKDEV(menu_major , 0);
    if(menu_major)
        ret = register_chrdev_region(dev, 1, DEVICE_NAME);
    else{
        ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
        menu_major = MAJOR(dev);   
    }
    if(ret < 0){
        printk("unable to get major %d \n",menu_major);
        return ret;   
    }
    menu_devp = kmalloc(sizeof(struct menu_dev),GFP_KERNEL);
    if(!menu_devp)
    {
        ret = -ENOMEM;
    }
    memset(menu_devp,0,sizeof(struct menu_dev));
    menu_setup_cdev(menu_devp, 0 );
    printk("menu driver initialized\n");
    return 0;   
}


//驱动卸载
void menu_exit(void)
{
    cdev_del(&menu_devp->cdev);
    unregister_chrdev_region(MKDEV(menu_major,0),1);
    printk("menu driver unistalled \n");
}

module_init(menu_init);
module_exit(menu_exit);

MODULE_LICENSE("Dual BSD/GPL");

这是我写得一个简单的按键驱动,只是想实现,如果按键就会产生中断,进入中断处理函数,打印信息。 我搞了几天,要不就是中断申请失败,要不就是中断申请成功,可是按键没有反应。想请高手帮我看看,**问题。

这是我的部分原理图,我想通过按下menu或者home键,能产生一个中断


这个图是上面代码执行结果。

论坛徽章:
0
2 [报告]
发表于 2012-08-20 16:51 |只看该作者
本帖最后由 jackyard 于 2012-08-20 17:08 编辑

你的这个不是共享中断吧,request_irq函数的每三个参数把IRQF_SHARED,先取掉。gpio_to_irq是获取对应书脚上的中断号,你的原理图上已经给你指出来了。还有你的这个按键原理图是矩阵按键。获取中断,还要作一些处理。EINT24不能配置成低电平,前面有一个4148的.好像你的这个4148是不是接反了。

论坛徽章:
0
3 [报告]
发表于 2012-08-20 20:37 |只看该作者
你好,
1.这个IRQF_SHARED是我乱试的,去掉肯定没问题。
2.你说的矩阵键盘,获取中断还要做些处理,能说的具体点吗
3. EINT24,为啥不能低电平,但是,EINT24,25,同时设置高电平,我也试过了。也是不行。

jackyard 发表于 2012-08-20 16:51
你的这个不是共享中断吧,request_irq函数的每三个参数把IRQF_SHARED,先取掉。gpio_to_irq是获取对应书脚上 ...

论坛徽章:
0
4 [报告]
发表于 2012-08-20 20:40 |只看该作者
前面有一个4148的.好像你的这个4148是不是接反了。??
还有这句话,我没看懂,4148,是什么?
jackyard 发表于 2012-08-20 16:51
你的这个不是共享中断吧,request_irq函数的每三个参数把IRQF_SHARED,先取掉。gpio_to_irq是获取对应书脚上 ...
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP