S3C6410按键驱动

来源:互联网 发布:vc http post json 编辑:程序博客网 时间:2024/05/02 06:46

S3C6410按键驱动——查询方式实现

OK6410总共有6个按键,按键分别接在GPN0~GPN5,原理图上根本没有这么说,原理图上说的是KEYINT!~KEYINT6,很明显这里是接在中断引脚上的,直接查询S3C6410的中断引脚就可以知道这个6个按键的接法,一下是用查询方法实现的按键驱动:

[cpp] view plaincopy
  1. #include <linux/module.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/init.h>  
  5. #include <linux/delay.h>  
  6. #include <asm/uaccess.h>  
  7. #include <asm/irq.h>  
  8. #include <asm/io.h>  
  9. #include <mach/regs-gpio.h>  
  10. #include <mach/hardware.h>  
  11. #include <linux/device.h>//新版内核  
  12.   
  13. static struct class *key_drv_class;  
  14. static struct class_device  *key_class_dev;  
  15. volatile unsigned long  *gpncon=NULL;  
  16. volatile unsigned long  *gpndat=NULL;  
  17.   
  18.   
  19. static int key_drv_open(struct inode  * inode, struct file * file)  
  20. {  
  21.     *gpncon &=~((0x3<<0)|(0x3<<2)|(0x3<<4)|(0x3<<6));  
  22.     return 0;  
  23. }  
  24. static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos)  
  25. {  
  26.   
  27.     return 0;  
  28. }  
  29. ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos)  
  30. {  
  31.     //返回四个引脚的电平  
  32.     unsigned char key_val[4];  
  33.     int regval;  
  34.   
  35.     if(size != sizeof(key_val))  
  36.         return -EINVAL;  
  37.     regval=*gpndat;  
  38.     key_val[0]  = (regval & (1<<0))?1:0;  
  39.     key_val[1]  = (regval & (1<<1))?1:0;  
  40.     key_val[2]  = (regval & (1<<2))?1:0;  
  41.     key_val[3]  = (regval & (1<<3))?1:0;  
  42.     copy_to_user(buf,key_val,sizeof(key_val));  
  43.       
  44.     return sizeof(key_val);  
  45. }  
  46.   
  47. static struct file_operations key_drv_openration ={  
  48.     .owner = THIS_MODULE,  
  49.     .open = key_drv_open,  
  50.     .write =key_drv_write,  
  51.     .read=key_drv_read,  
  52. };  
  53. int major;  
  54. static int key_drv_init(void)  
  55. {  
  56.     major=register_chrdev(0,"key_drv",&key_drv_openration);  
  57.       
  58.     key_drv_class = class_create(THIS_MODULE, "key_drv");  
  59.         //自动创建设备节点  
  60.     /* 新版的内核不能用class_device_create 要用device_create*/  
  61.     key_class_dev = device_create(key_drv_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */  
  62.           
  63.     gpncon = (volatile unsigned long*)ioremap(0x7F008830,16);  
  64.     gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位?  
  65.                         /*本例中使用的是unsigned long类型刚好是4个字节*/  
  66.   
  67.     return 0;  
  68. }  
  69. static void key_drv_exit(void)  
  70. {  
  71.     unregister_chrdev(major,"key_drv");  
  72.     device_unregister(key_class_dev);  
  73.     class_destroy(key_drv_class);  
  74.   
  75.     iounmap(gpncon);  
  76.     return 0;  
  77. }  
  78.   
  79. module_init(key_drv_init);  
  80. module_exit(key_drv_exit);  
  81. MODULE_LICENSE("GPL");  

一下是测试程序:

[cpp] view plaincopy
  1. #include<sys/types.h>  
  2. #include<sys/stat.h>  
  3. #include<fcntl.h>  
  4. #include<stdio.h>  
  5.   
  6. int main(int argc,char **argv)  
  7. {  
  8.     int fd;  
  9.     unsigned char key_val[4];  
  10.     int cnt;  
  11.     fd=open("/dev/key",O_RDWR);  
  12.     if(fd < 0)  
  13.         printf("can not open!!!\n");  
  14.     while(1)  
  15.         {  
  16.             read(fd,key_val,sizeof(key_val));  
  17.             if(!key_val[0]||!key_val[1]||!key_val[2]||!key_val[3])  
  18.                 {  
  19.                     printf("%04d key pressed :%d %d %d %d\n\n",cnt++,key_val[0],key_val[1],key_val[2],key_val[3]);  
  20.                 }  
  21.         }  
  22.     return 0;  
  23. }  

一下是测试运行结果:



1452 key pressed :1 0 1 1


1453 key pressed :1 0 1 1


1454 key pressed :1 0 1 1


1455 key pressed :1 0 1 1


1456 key pressed :1 0 1 1


1457 key pressed :1 0 1 1


1458 key pressed :1 0 1 1


1459 key pressed :1 0 1 1


1460 key pressed :1 0 1 1


1461 key pressed :1 0 1 1

让测试程序后台运行,查看CPU的运行状态:



Mem: 7968K used, 246548K free, 0K shrd, 0K buff, 2096K cached
CPU:  9.1% usr 90.8% sys  0.0% nic  0.0% idle  0.0% io  0.0% irq  0.0% sirq
Load average: 0.34 0.13 0.07 2/25 984
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
  983   969 root     R      792  0.3   0 99.6 ./main
  984   969 root     R     2268  0.8   0  0.2 top
  969     1 root     S     2268  0.8   0  0.0 -/bin/sh
    1     0 root     S     2264  0.8   0  0.0 init
    4     2 root     SW       0  0.0   0  0.0 [kworker/0:0]
    5     2 root     SW       0  0.0   0  0.0 [kworker/u:0]

可以看出按键 程序的CPU占用率很大,这种驱动方式很不好。


S3C6410按键驱动--中断方式

[cpp] view plaincopy
  1. #include <linux/module.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/init.h>  
  5. #include <linux/delay.h>  
  6. #include <asm/uaccess.h>  
  7. #include <asm/irq.h>  
  8. #include <asm/io.h>  
  9. #include <mach/regs-gpio.h>  
  10. #include <mach/hardware.h>  
  11. #include <linux/interrupt.h>  
  12. #include <linux/sched.h>  
  13. #include <linux/device.h>//新版内核  
  14.   
  15. #include <linux/gpio.h>  
  16. #include <plat/gpio-cfg.h>  
  17.   
  18.   
  19. static struct class *key_irq_class;  
  20. static struct class_device  *key_class_irq;  
  21. volatile unsigned long  *gpncon=NULL;  
  22. volatile unsigned long  *gpndat=NULL;  
  23.   
  24. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
  25.   
  26. /* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */  
  27. static volatile int ev_press = 0;  
  28. struct key_desc{  
  29.     unsigned int pin;  
  30.     unsigned int key_val;  
  31.     };  
  32. /*键值:按下时,0x01,0x02,0x03,0x04,0x05,0x06*/  
  33. /*键值:松开时,0x81,0x82,0x83,0x84,0x85,0x86*/  
  34. static unsigned char key_num;  
  35. struct key_desc keys_desc[6]={  
  36.     {1,0x01},  
  37.     {2,0x02},  
  38.     {3,0x03},  
  39.     {4,0x04},  
  40.     {5,0x05},  
  41.     {6,0x06},  
  42. };  
  43.   
  44. static irqreturn_t key_irq(int irq, void *dev_id)  
  45. {  
  46.     struct key_desc *pin=(struct key_desc*)dev_id;  
  47.     unsigned int pinval;  
  48.     pinval=gpio_get_value(S3C64XX_GPN(pin->pin));  
  49.     if(pinval)  
  50.         {  
  51.             key_num=0x80|pin->key_val;  
  52.         }  
  53.     else  
  54.         {  
  55.             key_num=pin->key_val;  
  56.         }  
  57.     //printk("*********************");  
  58.     //printk("key_num= %x\n",key_num);  
  59.     //printk("*********************");  
  60.     //ev_press=1;/*表示中断发生了*/  
  61.     wake_up_interruptible(&button_waitq);/*唤醒休眠的进程*/  
  62.     return IRQ_HANDLED;  
  63. }  
  64.   
  65. static int key_drv_open(struct inode  * inode, struct file * file)  
  66. {  
  67.     request_irq(IRQ_EINT(1),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S1",&keys_desc[0]);  
  68.     request_irq(IRQ_EINT(2),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S2",&keys_desc[1]);  
  69.     request_irq(IRQ_EINT(3),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S3",&keys_desc[2]);  
  70.     request_irq(IRQ_EINT(4),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S4",&keys_desc[3]);  
  71.     request_irq(IRQ_EINT(5),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S5",&keys_desc[4]);  
  72.     request_irq(IRQ_EINT(6),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S6",&keys_desc[5]);  
  73.     return 0;  
  74. }  
  75. static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos)  
  76. {  
  77.   
  78.     return 0;  
  79. }  
  80. ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos)  
  81. {  
  82.     //返回四个引脚的电平  
  83.     if(size != 1)  
  84.         return -EINVAL;  
  85.     /*如果没有按键动作发生就休眠*/  
  86.     wait_event_interruptible(button_waitq, ev_press);  
  87.     /*如果有按键动作,返回键值*/  
  88.     copy_to_user(buf,&key_num,1);  
  89.     ev_press=0;  
  90.     return 1;  
  91. }  
  92. int key_drv_release(struct inode * inode, struct file * file)  
  93. {  
  94.     free_irq(IRQ_EINT(1),&keys_desc[0]);  
  95.     free_irq(IRQ_EINT(2),&keys_desc[1]);  
  96.     free_irq(IRQ_EINT(3),&keys_desc[2]);  
  97.     free_irq(IRQ_EINT(4),&keys_desc[3]);  
  98.     free_irq(IRQ_EINT(5),&keys_desc[4]);  
  99.     free_irq(IRQ_EINT(6),&keys_desc[5]);  
  100.       
  101.     return 0;  
  102. }  
  103. static struct file_operations key_drv_openration ={  
  104.     .owner = THIS_MODULE,  
  105.     .open = key_drv_open,  
  106.     .write =key_drv_write,  
  107.     .read=key_drv_read,  
  108.     .release=key_drv_release,  
  109. };  
  110. int major;  
  111. static int key_drv_init(void)  
  112. {  
  113.     major=register_chrdev(0,"key_irq",&key_drv_openration);  
  114.       
  115.     key_irq_class = class_create(THIS_MODULE, "key_irq");  
  116.         //自动创建设备节点  
  117.     /* 新版的内核不能用class_device_create 要用device_create*/  
  118.     key_class_irq = device_create(key_irq_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */  
  119.           
  120.     gpncon = (volatile unsigned long*)ioremap(0x7F008830,16);  
  121.     gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位?  
  122.                         /*本例中使用的是unsigned long类型刚好是4个字节*/  
  123.   
  124.     return 0;  
  125. }  
  126. static void key_drv_exit(void)  
  127. {  
  128.     unregister_chrdev(major,"key_irq");  
  129.     device_unregister(key_class_irq);  
  130.     class_destroy(key_irq_class);  
  131.   
  132.     iounmap(gpncon);  
  133.     return 0;  
  134. }  
  135.   
  136. module_init(key_drv_init);  
  137. module_exit(key_drv_exit);  
  138. MODULE_LICENSE("GPL");  

测试程序:

[cpp] view plaincopy
  1. #include<sys/types.h>  
  2. #include<sys/stat.h>  
  3. #include<fcntl.h>  
  4. #include<stdio.h>  
  5.   
  6. int main(int argc,char **argv)  
  7. {  
  8.     int fd;  
  9.     unsigned char key_val;  
  10.     int cnt;  
  11.     fd=open("/dev/key",O_RDWR);  
  12.     if(fd < 0)  
  13.         {  
  14.             printf("can not open!!!\n");  
  15.             return 0;  
  16.         }  
  17.     while(1)  
  18.         {  
  19.             read(fd,&key_val,1);  
  20.             printf("key_val = 0x%x\n", key_val);  
  21.         }  
  22.     return 0;  
  23. }  
测试结果:

[root@Pillar /driver/key/key_IRQ]#./main &
[root@Pillar /driver/key/key_IRQ]#*********************key_num= 81
*********************key_val = 0x81
*********************key_num= 82
*********************key_val = 0x82
*********************key_num= 3
******************************************key_num= 3
******************************************key_num= 83
*********************key_val = 0x3


0 0
原创粉丝点击