按键中断实验

按键中断实现流程:

1.设备树中添加中断信息:f9--key1,f7---key2,f8---key3

/*myirq{
    interrupt-parent = <&gpiof>;
     interrupts = <7 0>, <8 0>, <9 0>;//第一个成员指的是gpio编号,第二个成员表示触发方式,0表示默认属性
};*/

内核顶层目录make dtbs 编译,拷贝到tftpboot目录下,重新启动开发板加载设备树文件

2.编写驱动代码:

定义3个中断号,在入口函数中根据节点信息申请中断号

        node=of_find_node_by_name(NULL,"myirq");

        irqno[0]=irq_of_parse_and_map(node,2);

将中断号注册进内核(此步骤会跳转到回调函数,执行自定义的中断操作)

    ret=request_irq(irqno[0],irq_handler1,IRQF_TRIGGER_FALLING,"key1_inte",NULL);

        参数1:软中断号,参数2:中断处理函数(函数指针),参数3:中断触发方式(下降沿触发,上升沿触发,高电平,低电平触发)参数4:中断的名字,自己指定,参数5:在这个函数里传给中断处理函数的参数,根据实际情况使用

在出口注销中断号

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
#include<linux/timer.h>
#include<linux/jiffies.h>
#include<linux/of_irq.h>
#include<linux/interrupt.h>

struct gpio_desc *gpinum[3];//存放老版本
struct device_node *nod;
//定义指针指向获取的设备树节点信息空间
 struct device_node *node;
 int ret;
 unsigned int irqno[3];//用于接收软中断号
 unsigned int count=0;//用于计数,中断发生一次+1

//中断处理函数顶部
irqreturn_t irq_handler1(int irqno,void *dev)
{
    count++;
    printk("key1 interrupt....%d...\n",count);
    gpiod_set_value(gpinum[0],!gpiod_get_value(gpinum[0]));
    return IRQ_HANDLED;
}
irqreturn_t irq_handler2(int irqno,void *dev)
{
    count++;
    printk("key2 interrupt....%d...\n",count);
    gpiod_set_value(gpinum[1],!gpiod_get_value(gpinum[1]));
    return IRQ_HANDLED;
}
irqreturn_t irq_handler3(int irqno,void *dev)
{
    count++;
    printk("key3 interrupt....%d...\n",count);
    gpiod_set_value(gpinum[2],!gpiod_get_value(gpinum[2]));
    return IRQ_HANDLED;
}

static int __init mycdev_init(void)
{
    //通过名字获取设备树节点信息
    node=of_find_node_by_name(NULL,"myirq");
    if(node==NULL)
    {
        printk("通过名字解析设备树节点失败\n");
        return -EFAULT;
    }
    printk("成功解析到设备树节点\n");
    //根据设备树节点信息获取软中断号key1
    irqno[0]=irq_of_parse_and_map(node,2);
    if(irqno[0]==0)
    {
        printk("获取软中断号失败\n");
        return EINVAL;
    }
    printk("获取软中断号成功\n");
    //将中断注册进内核
    ret=request_irq(irqno[0],irq_handler1,IRQF_TRIGGER_FALLING,"key1_inte",NULL);
    if(ret)
    {
        printk("注册中断失败\n");
        return ret;
    }
    printk("注册中断1成功\n");
    //根据设备树节点信息获取软中断号key2
    irqno[1]=irq_of_parse_and_map(node,0);
    if(irqno[1]==0)
    {
        printk("获取软中断号失败\n");
        return EINVAL;
    }
    printk("获取软中断号成功\n");
    //将中断注册进内核
    ret=request_irq(irqno[1],irq_handler2,IRQF_TRIGGER_FALLING,"key2_inte",NULL);
    if(ret)
    {
        printk("注册中断失败\n");
        return ret;
    }
    printk("注册中断2成功\n");
    //根据设备树节点信息获取软中断号key3
    irqno[2]=irq_of_parse_and_map(node,1);
    if(irqno[2]==0)
    {
        printk("获取软中断号失败\n");
        return EINVAL;
    }
    printk("获取软中断号成功\n");
    //将中断注册进内核
    ret=request_irq(irqno[2],irq_handler3,IRQF_TRIGGER_FALLING,"key3_inte",NULL);
    if(ret)
    {
        printk("注册中断失败\n");
        return ret;
    }
    printk("注册中断3成功\n");
 //灯的初始化
    //1.通过名字获取设备节点信息
    nod=of_find_node_by_name(NULL,"myleds");
    //获取并申请gpio编号
    gpinum[0]=gpiod_get_from_of_node(nod,"myled1",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpinum[0]))
    {
        printk("获取gpioe10编号失败\n");
        //将错误码指针转换成错误码
        return PTR_ERR(gpinum[0]);
    }
    printk("获取gpio编号成功\n");
    gpinum[1]=gpiod_get_from_of_node(nod,"myled2",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpinum[1]))
    {
        printk("获取gpio编号失败\n");
        //将错误码指针转换成错误码
        return PTR_ERR(gpinum[1]);
    }
    printk("获取gpiof10编号成功\n");
    gpinum[2]=gpiod_get_from_of_node(nod,"myled3",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpinum[2]))
    {
        printk("获取gpio编号失败\n");
        //将错误码指针转换成错误码
        return PTR_ERR(gpinum[2]);
    }
    printk("获取gpioe8编号成功\n");

    //设置管脚输出模式
    //gpiod_direction_output(gpinum,0);
   return 0;
}
static void __exit mycdev_exit(void)
{
    //熄灭led1
    gpiod_set_value(gpinum[0],0);
    //卸载驱动
    gpiod_put(gpinum[0]);
    //熄灭led2
    gpiod_set_value(gpinum[1],0);
    //卸载驱动
    gpiod_put(gpinum[1]);
    //熄灭led3
    gpiod_set_value(gpinum[2],0);
    //卸载驱动
    gpiod_put(gpinum[2]);
   //中断的注销
   free_irq(irqno[0],NULL);
   free_irq(irqno[1],NULL);
   free_irq(irqno[2],NULL);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

实验现象

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值