TA的每日心情 | 开心 6 天前 |
---|
签到天数: 1077 天 连续签到: 1 天 [LV.10]以坛为家III
|
学习linux下按键中断程序的测试。
一、硬件部分
按键硬件部分电路
二、程序部分
2.1、修改设备树文件
将设备中,按键这个几个引脚屏蔽掉
2.2、编译设备树
编译设备树,并将编译的文件复制到开发板
2.3、开发板更新设备数据文件
执行命令:
root@ELF1:~# sync
root@ELF1:~# reboot
2.4、驱动程序
key_irq.c
- #include <linux/module.h> // 包含模块相关函数的头文件
- #include <linux/fs.h> // 包含文件系统相关函数的头文件
- #include <linux/uaccess.h> // 包含用户空间数据访问函数的头文件
- #include <linux/cdev.h> //包含字符设备头文件
- #include <linux/device.h>
- #include <linux/gpio.h>
- #include <linux/interrupt.h>
- #define DEVICE_NAME "key_irq" // 设备名称
- #define GPIO_KEY1_PIN_NUM 132 //K1
- #define GPIO_KEY2_PIN_NUM 130 //K1
- #define GPIO_KEY3_PIN_NUM 137 //K3
- #define KEY1_IRQ gpio_to_irq(GPIO_KEY1_PIN_NUM)
- #define KEY2_IRQ gpio_to_irq(GPIO_KEY2_PIN_NUM)
- #define KEY3_IRQ gpio_to_irq(GPIO_KEY3_PIN_NUM)
- static struct workqueue_struct *my_workqueue;
- static struct work_struct my_work;
- static dev_t dev_num; //分配的设备号
- struct cdev my_cdev; //字符设备指针
- int major; //主设备号
- int minor; //次设备号
- static struct class *key_irq;
- static struct device *my_device;
- static irqreturn_t key1_interrupt_handler(int irq, void *dev_id)
- {
- int key1_state = gpio_get_value(GPIO_KEY1_PIN_NUM);
- if (key1_state) {
- printk(KERN_INFO "key1 released\n");
- } else {
- printk(KERN_INFO "key1 pressed\n");
- }
- return IRQ_HANDLED;
- }
- static irqreturn_t key2_interrupt_handler(int irq, void *dev_id)
- {
- int key2_state = gpio_get_value(GPIO_KEY2_PIN_NUM);
- if (key2_state) {
- printk(KERN_INFO "key2 released\n");
- } else {
- printk(KERN_INFO "key2 pressed\n");
- }
- return IRQ_HANDLED;
- }
- static irqreturn_t key3_interrupt_handler(int irq, void *dev_id)
- {
- int key3_state = gpio_get_value(GPIO_KEY3_PIN_NUM);
- if (key3_state) {
- printk(KERN_INFO "key3 released\n");
- } else {
- printk(KERN_INFO "key3 pressed\n");
- }
- return IRQ_HANDLED;
- }
- static int device_open(struct inode *inode, struct file *file)
- {
- gpio_direction_input(GPIO_KEY1_PIN_NUM);
- gpio_direction_input(GPIO_KEY2_PIN_NUM);
- gpio_direction_input(GPIO_KEY3_PIN_NUM);
- printk(KERN_INFO "This is device_open.\n");
- return 0;
- }
- static int device_release(struct inode *inode, struct file *file)
- {
- gpio_direction_input(GPIO_KEY1_PIN_NUM);
- gpio_direction_input(GPIO_KEY2_PIN_NUM);
- gpio_direction_input(GPIO_KEY3_PIN_NUM);
- printk(KERN_INFO "This is device_release.\n");
- return 0;
- }
- static struct file_operations fops =
- {
- .owner = THIS_MODULE,
- .open = device_open,
- .release = device_release,
- };
- static int __init keyirq_init(void)
- {
- int ret;
- gpio_free(GPIO_KEY1_PIN_NUM);
- gpio_free(GPIO_KEY2_PIN_NUM);
- gpio_free(GPIO_KEY3_PIN_NUM);
- gpio_request(GPIO_KEY1_PIN_NUM, "key_irq1");
- gpio_request(GPIO_KEY2_PIN_NUM, "key_irq2");
- gpio_request(GPIO_KEY3_PIN_NUM, "key_irq3");
- /*if (gpio_request(GPIO_KEY_PIN_NUM, "key_irq"))
- {
- printk("request %s gpio faile \n", "key_irq");
- return -1;
- }*/
- gpio_direction_input(GPIO_KEY1_PIN_NUM);
- gpio_direction_input(GPIO_KEY2_PIN_NUM);
- gpio_direction_input(GPIO_KEY3_PIN_NUM);
- request_irq(KEY1_IRQ, key1_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq1", NULL);
- request_irq(KEY2_IRQ, key2_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq2", NULL);
- request_irq(KEY3_IRQ, key3_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq3", NULL);
- // 注册中断处理函数
- /*ret = request_irq(BUTTON_IRQ, button_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq", NULL);
- if (ret < 0) {
- printk(KERN_ALERT "Failed to register interrupt handler\n");
- gpio_free(GPIO_KEY_PIN_NUM);
- return ret;
- }*/
-
- // 注册字符设备驱动程序
- ret = alloc_chrdev_region(&dev_num,0,1,DEVICE_NAME);
- if (ret < 0)
- {
- printk(KERN_ALERT "Failed to allocate device number: %d\n", ret);
- return ret;
- }
- major=MAJOR(dev_num);
- minor=MINOR(dev_num);
- printk(KERN_INFO "major number: %d\n",major);
- printk(KERN_INFO "minor number: %d\n",minor);
- my_cdev.owner = THIS_MODULE;
- cdev_init(&my_cdev,&fops);
- cdev_add(&my_cdev,dev_num,1);
- // 创建设备类
- key_irq = class_create(THIS_MODULE, "key_irq");
- if (IS_ERR(key_irq))
- {
- pr_err("Failed to create class\n");
- return PTR_ERR(key_irq);
- }
- // 创建设备节点并关联到设备类
- my_device = device_create(key_irq, NULL, MKDEV(major, minor), NULL, DEVICE_NAME);
- if (IS_ERR(my_device))
- {
- pr_err("Failed to create device\n");
- class_destroy(key_irq);
- return PTR_ERR(my_device);
- }
- printk(KERN_INFO "Device registered successfully.\n");
- return 0;
- }
- static void __exit keyirq_exit(void)
- {
- // 释放中断
- free_irq(KEY1_IRQ, NULL);
- free_irq(KEY2_IRQ, NULL);
- free_irq(KEY3_IRQ, NULL);
- // 在这里执行驱动程序的清理操作
- gpio_free(GPIO_KEY1_PIN_NUM);
- gpio_free(GPIO_KEY2_PIN_NUM);
- gpio_free(GPIO_KEY3_PIN_NUM);
- // 销毁设备节点
- device_destroy(key_irq, MKDEV(major, minor));
- // 销毁设备类
- class_destroy(key_irq);
- // 删除字符设备
- cdev_del(&my_cdev);
- // 注销字符设备驱动程序
- unregister_chrdev(0, DEVICE_NAME);
- printk(KERN_INFO "Device unregistered.\n");
- }
- module_init(keyirq_init);
- module_exit(keyirq_exit);
- MODULE_LICENSE("GPL"); // 指定模块的许可证信息
- MODULE_AUTHOR("Your Name"); // 指定模块的作者信息
- MODULE_DESCRIPTION("A simple character device driver"); // 指定模块的描述信息
复制代码
2.5、编译
编译完成后,编译的文件复制到开发板
三、运行
3.1、插入模块
3.2、按键测试
按下按键后,打印出相应按键的状态
3.3、卸载模块
以上就是测试按键中断的测试过程。
|
|