查看: 631|回复: 0

[评测分享] 【更适合初学者的开发板ELF 1】+ 按键中断测试

[复制链接]
  • TA的每日心情
    开心
    2024-4-28 14:52
  • 签到天数: 1058 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2023-12-13 17:31:35 | 显示全部楼层 |阅读模式
    分享到:
    学习linux下按键中断程序的测试。

    一、硬件部分

    按键硬件部分电路
    001.png

    二、程序部分

    2.1、修改设备树文件
    将设备中,按键这个几个引脚屏蔽掉
    002.png

    2.2、编译设备树
    003.png
    编译设备树,并将编译的文件复制到开发板

    2.3、开发板更新设备数据文件
    执行命令:
    root@ELF1:~# sync
    root@ELF1:~# reboot


    2.4、驱动程序
    key_irq.c
    1. #include <linux/module.h>       // 包含模块相关函数的头文件
    2. #include <linux/fs.h>           // 包含文件系统相关函数的头文件
    3. #include <linux/uaccess.h>      // 包含用户空间数据访问函数的头文件
    4. #include <linux/cdev.h>         //包含字符设备头文件
    5. #include <linux/device.h>
    6. #include <linux/gpio.h>
    7. #include <linux/interrupt.h>

    8. #define DEVICE_NAME "key_irq"  // 设备名称
    9. #define GPIO_KEY1_PIN_NUM 132   //K1
    10. #define GPIO_KEY2_PIN_NUM 130   //K1
    11. #define GPIO_KEY3_PIN_NUM 137   //K3
    12. #define KEY1_IRQ  gpio_to_irq(GPIO_KEY1_PIN_NUM)
    13. #define KEY2_IRQ  gpio_to_irq(GPIO_KEY2_PIN_NUM)
    14. #define KEY3_IRQ  gpio_to_irq(GPIO_KEY3_PIN_NUM)

    15. static struct workqueue_struct *my_workqueue;
    16. static struct work_struct my_work;

    17. static dev_t dev_num;   //分配的设备号
    18. struct  cdev my_cdev;          //字符设备指针
    19. int major;  //主设备号
    20. int minor;  //次设备号
    21. static struct class *key_irq;
    22. static struct device *my_device;

    23. static irqreturn_t key1_interrupt_handler(int irq, void *dev_id)
    24. {
    25.     int key1_state = gpio_get_value(GPIO_KEY1_PIN_NUM);
    26.     if (key1_state) {
    27.         printk(KERN_INFO "key1 released\n");
    28.     } else {
    29.         printk(KERN_INFO "key1 pressed\n");
    30.     }
    31.     return IRQ_HANDLED;
    32. }

    33. static irqreturn_t key2_interrupt_handler(int irq, void *dev_id)
    34. {
    35.     int key2_state = gpio_get_value(GPIO_KEY2_PIN_NUM);
    36.     if (key2_state) {
    37.         printk(KERN_INFO "key2 released\n");
    38.     } else {
    39.         printk(KERN_INFO "key2 pressed\n");
    40.     }
    41.     return IRQ_HANDLED;
    42. }

    43. static irqreturn_t key3_interrupt_handler(int irq, void *dev_id)
    44. {
    45.     int key3_state = gpio_get_value(GPIO_KEY3_PIN_NUM);
    46.     if (key3_state) {
    47.         printk(KERN_INFO "key3 released\n");
    48.     } else {
    49.         printk(KERN_INFO "key3 pressed\n");
    50.     }
    51.     return IRQ_HANDLED;
    52. }

    53. static int device_open(struct inode *inode, struct file *file)
    54. {
    55.     gpio_direction_input(GPIO_KEY1_PIN_NUM);
    56.     gpio_direction_input(GPIO_KEY2_PIN_NUM);
    57.     gpio_direction_input(GPIO_KEY3_PIN_NUM);
    58.     printk(KERN_INFO "This is device_open.\n");
    59.     return 0;
    60. }

    61. static int device_release(struct inode *inode, struct file *file)
    62. {
    63.     gpio_direction_input(GPIO_KEY1_PIN_NUM);
    64.     gpio_direction_input(GPIO_KEY2_PIN_NUM);
    65.     gpio_direction_input(GPIO_KEY3_PIN_NUM);
    66.     printk(KERN_INFO "This is device_release.\n");
    67.     return 0;
    68. }

    69. static struct file_operations fops =
    70. {
    71.     .owner = THIS_MODULE,
    72.     .open = device_open,
    73.     .release = device_release,
    74. };

    75. static int __init keyirq_init(void)
    76. {
    77.     int ret;
    78.     gpio_free(GPIO_KEY1_PIN_NUM);
    79.     gpio_free(GPIO_KEY2_PIN_NUM);
    80.     gpio_free(GPIO_KEY3_PIN_NUM);
    81.     gpio_request(GPIO_KEY1_PIN_NUM, "key_irq1");
    82.     gpio_request(GPIO_KEY2_PIN_NUM, "key_irq2");
    83.     gpio_request(GPIO_KEY3_PIN_NUM, "key_irq3");
    84.         /*if (gpio_request(GPIO_KEY_PIN_NUM, "key_irq"))
    85.     {
    86.                 printk("request %s gpio faile \n", "key_irq");
    87.                 return -1;
    88.         }*/
    89.     gpio_direction_input(GPIO_KEY1_PIN_NUM);
    90.     gpio_direction_input(GPIO_KEY2_PIN_NUM);
    91.     gpio_direction_input(GPIO_KEY3_PIN_NUM);

    92.     request_irq(KEY1_IRQ, key1_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq1", NULL);
    93.     request_irq(KEY2_IRQ, key2_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq2", NULL);
    94.     request_irq(KEY3_IRQ, key3_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq3", NULL);

    95.     // 注册中断处理函数
    96.     /*ret = request_irq(BUTTON_IRQ, button_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq", NULL);
    97.     if (ret < 0) {
    98.         printk(KERN_ALERT "Failed to register interrupt handler\n");
    99.         gpio_free(GPIO_KEY_PIN_NUM);
    100.         return ret;
    101.     }*/
    102.        
    103.     // 注册字符设备驱动程序
    104.     ret = alloc_chrdev_region(&dev_num,0,1,DEVICE_NAME);
    105.     if (ret < 0)
    106.     {
    107.         printk(KERN_ALERT "Failed to allocate device number: %d\n", ret);
    108.         return ret;
    109.     }
    110.     major=MAJOR(dev_num);
    111.     minor=MINOR(dev_num);
    112.         printk(KERN_INFO "major number: %d\n",major);
    113.         printk(KERN_INFO "minor number: %d\n",minor);

    114.         my_cdev.owner = THIS_MODULE;
    115.     cdev_init(&my_cdev,&fops);
    116.     cdev_add(&my_cdev,dev_num,1);
    117.     // 创建设备类
    118.     key_irq = class_create(THIS_MODULE, "key_irq");
    119.     if (IS_ERR(key_irq))
    120.     {
    121.         pr_err("Failed to create class\n");
    122.         return PTR_ERR(key_irq);
    123.     }
    124.   // 创建设备节点并关联到设备类
    125.     my_device = device_create(key_irq, NULL, MKDEV(major, minor), NULL, DEVICE_NAME);
    126.     if (IS_ERR(my_device))
    127.     {
    128.         pr_err("Failed to create device\n");
    129.         class_destroy(key_irq);
    130.         return PTR_ERR(my_device);
    131.     }
    132.     printk(KERN_INFO "Device registered successfully.\n");
    133.     return 0;
    134. }

    135. static void __exit keyirq_exit(void)
    136. {
    137.     // 释放中断
    138.     free_irq(KEY1_IRQ, NULL);
    139.     free_irq(KEY2_IRQ, NULL);
    140.     free_irq(KEY3_IRQ, NULL);
    141.     // 在这里执行驱动程序的清理操作
    142.     gpio_free(GPIO_KEY1_PIN_NUM);
    143.     gpio_free(GPIO_KEY2_PIN_NUM);
    144.     gpio_free(GPIO_KEY3_PIN_NUM);
    145.     // 销毁设备节点
    146.     device_destroy(key_irq, MKDEV(major, minor));
    147.     // 销毁设备类
    148.     class_destroy(key_irq);
    149.     // 删除字符设备
    150.     cdev_del(&my_cdev);
    151.     // 注销字符设备驱动程序
    152.     unregister_chrdev(0, DEVICE_NAME);
    153.     printk(KERN_INFO "Device unregistered.\n");
    154. }

    155. module_init(keyirq_init);
    156. module_exit(keyirq_exit);

    157. MODULE_LICENSE("GPL");      // 指定模块的许可证信息
    158. MODULE_AUTHOR("Your Name"); // 指定模块的作者信息
    159. MODULE_DESCRIPTION("A simple character device driver"); // 指定模块的描述信息
    复制代码



    2.5、编译
    200.png
    编译完成后,编译的文件复制到开发板

    三、运行

    3.1、插入模块
    201.png

    3.2、按键测试
    按下按键后,打印出相应按键的状态
    202.png

    3.3、卸载模块
    203.png

    以上就是测试按键中断的测试过程。
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-5-12 07:15 , Processed in 0.116535 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.