回答

收藏

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

#板卡评测 #板卡评测 1822 人阅读 | 0 人回复 | 2023-12-13

学习linux下按键中断程序的测试。

一、硬件部分

按键硬件部分电路


二、程序部分

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


2.2、编译设备树

编译设备树,并将编译的文件复制到开发板

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、编译

编译完成后,编译的文件复制到开发板

三、运行

3.1、插入模块


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


3.3、卸载模块


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

使用道具 举报

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

本版积分规则

关闭

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