Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43513
  • 博文数量: 4
  • 博客积分: 185
  • 博客等级: 入伍新兵
  • 技术积分: 231
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-31 16:56
文章分类
文章存档

2012年(4)

我的朋友

分类: LINUX

2012-11-30 07:33:10

目标:编写一个按键驱动程序,如果有按键按下就打印一些信息。

环境:TQ2440 Ubuntu12.04linux-2.6.25


 

 

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/init.h>
  5. #include <linux/device.h>
  6. #include <linux/miscdevice.h>
  7. #include <linux/delay.h>
  8. #include <linux/mm.h>
  9. #include <linux/types.h>
  10. #include <linux/cdev.h>
  11. #include <asm/irq.h>
  12. #include <asm/arch/regs-gpio.h>
  13. #include <asm/arch/map.h>
  14. #include <asm/arch/regs-irq.h>
  15. #include <asm/io.h>
  16. #include <asm/hardware.h>
  17. #include <asm/uaccess.h>
  18. #include <asm/system.h>

  19. volatile unsigned long *gpfcon;
  20. volatile unsigned long *gpfdat;

  21. static struct class *btn_cls; //为了自动创建设备节点
  22. static struct class_device *btn_cls_dev; //为了自动创建设备节点
  23. static struct cdev cdev;
  24. static int major = 0;

  25. static int btn_open(struct inode *inode, struct file *file)
  26. {
  27.     *gpfcon &= ~((0x3 <<(2*0)) | (0x3 << (2*1)) | (0x3 <<(2*2))//设置按键的引脚为输入引
  28.                 | (0x3 << (2*4)));                             //
  29.     
  30.     return 0;
  31. }
  32. ssize_t btn_read(struct file *file, char __user * buf,
  33.          size_t len, loff_t * ppos)
  34. {
  35.     unsigned long rev;
  36.     unsigned char key_val[4];

  37.     if (len != sizeof(key_val))
  38.         return -EINVAL;
  39.     
  40.     rev = *gpfdat; //读取寄存器的值
  41.     key_val[0] = (rev & (1<<0)) ? 0 : 1;//获取K4的状态,是否按下
  42.     key_val[1] = (rev & (1<<1)) ? 0 : 1;//获取K1的状态,是否按下
  43.     key_val[2] = (rev & (1<<2)) ? 0 : 1;//获取K3的状态,是否按下
  44.     key_val[3] = (rev & (1<<4)) ? 0 : 1;//获取K2的状态,是否按下
  45.     
  46.     copy_to_user(buf, key_val, sizeof(key_val));
  47.     
  48.     return 0;
  49. }
  50. static int btn_release(struct inode *inode, struct file *file)
  51. {
  52.     printk("button release\n");
  53.     return 0;
  54. }


  55. const struct file_operations btn_op =
  56. {
  57.     .owner     = THIS_MODULE,
  58.     .open = btn_open,
  59.     .read = btn_read,
  60.     .release = btn_release,
  61. };

  62. static int btn_val_init()
  63. {
  64.     dev_t devid;
  65.     int rc;
  66.     if (major)
  67.     {
  68.         devid = MKDEV(major, 0);
  69.         rc = register_chrdev_region(devid, 1, "button");
  70.     }
  71.     else
  72.     {
  73.         rc = alloc_chrdev_region(&devid, 0, 1, "button");
  74.         major = MAJOR(devid);
  75.     }
  76.     
  77.     if (rc < 0)
  78.     {
  79.         printk(KERN_ERR, "can't get major");
  80.         return -ENODEV;
  81.     }
  82.     
  83.     cdev_init(&cdev, &btn_op);
  84.     cdev_add(&cdev, devid, 1);

  85.     btn_cls = class_create(THIS_MODULE, "button");
  86.     btn_cls_dev = class_device_create(btn_cls, NULL, MKDEV(major, 0), NULL, "button0");//这个button0才是自动创建的设备节点的名字,可以和其他的名字不一样,见上面

  87.     gpfcon = (volatile unsigned long)ioremap(0x56000050, 16);//GPFCON寄存器的地址映射
  88.     gpfdat = gpfcon 1;
  89.     
  90.     return 0;
  91. }

  92. static void btn_val_exit()
  93. {
  94.     class_device_destroy(btn_cls, MKDEV(major, 0));
  95.     class_destroy(btn_cls);
  96.     cdev_del(&cdev);
  97.     unregister_chrdev_region(MKDEV(major, 0), 1);
  98. }

  99. module_init(btn_val_init);
  100. module_exit(btn_val_exit);
  101. MODULE_AUTHOR("xiaoming");
  102. MODULE_DESCRIPTION("read the value of button");
  103. MODULE_LICENSE("GPL");

运行结果:


 

 

测试小例子:


 

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>

  4. int main()
  5. {
  6.     int fd;
  7.     unsigned char key_val[4];

  8.     fd = open("/dev/button0", O_RDWR);//这个名字是 class_device_create 时的名字
  9.     if (fd < 0)
  10.     {
  11.         printf("open /dev/button0 failed\n");
  12.         return -1;
  13.     }
  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("key[0] = %d, key[1] = %d, key[2] = %d, key[3] = %d\n",
  20.                 key_val[0], key_val[1], key_val[2], key_val[3]);
  21.         }
  22.     }
  23.     
  24.     return 0;
  25. }

运行结果:

当按下按键时就会打印一些信息


 

 

                图1 TQ2440底板原理图

 

 

   图2 TQ2440核心板原理图

 

  图3.s3c2440.pdf

 

图4.s3c2440.pdf

 

 

阅读(999) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~