• 字符设备驱动(二)---key的使用:查询方式


    ---恢复内容开始---

    一、硬件电路

    1.1 电路原理图

        

      S1-S5共5个按键,其中,S2-S4为中断按键,S1为复位按键。S1直接为硬件复位电路,并不需要我们写进驱动。

      单片机接口如下图:

      

      

      

      

       由图中可以看出,EINT0、EINT2和EINT11作为输出引脚,EINT19是作为输入引脚。

       EINT0和EINT2对应的GPIO引脚为GPF0和GPF2;EINT11和EINT19对应的GPIO引脚为GPF3和GPF11.

       作为查询方式使用,就不使用中断来用,则将引脚定义为输入状态。

    1.2 对应的寄存器配置

      1.2.1 GPF引脚:

        

        GPF引脚主要对应三个寄存器,GPFCON,GPFDAT和GPFUP。

      • GPFCON:配置F引脚的寄存器
      • GPFDAT:F引脚的数据寄存器
      • GPFUP:F引脚的上拉使能寄存器

        GPF0和GPF2引脚可配置的属性如下:

        

        

        GPF0和GPF2作为输入在使能,则应将其配置为00。

      1.2.2 GPG引脚

        GPG引脚类似GPF引脚。

        

    二、代码

      2.1 驱动代码

      1 /*
      2  * =====================================================================================
      3  *       Filename:  key.c
      4  *    Description:  
      5  *        Version:  1.0
      6  *        Created:  2017年05月24日 15时39分34秒
      7  *         Author:  YOUR NAME (), 
      8  *   Organization:  
      9  * =====================================================================================
     10  */
     11 
     12 #include <linux/module.h>
     13 #include <linux/kernel.h>
     14 #include <linux/fs.h>
     15 #include <linux/init.h>
     16 #include <linux/delay.h>
     17 #include <asm/irq.h>
     18 #include <linux/interrupt.h>
     19 #include <asm/uaccess.h>
     20 #include <asm/arch/regs-gpio.h>
     21 #include <asm/hardware.h>
     22 
     23 #define DEVICE_NAME        "keys"
     24 #define KEY_MAJOR        232
     25 
     26 static struct class *keys_class;
     27 static struct class_device *keys_class_dev[4];
     28 static unsigned long gpio_va;    //gpio物理地址映射为虚拟地址变量
     29 #define GPIO_OFT(x) ((x) - 0x56000000)
     30 /* GPF引脚物理地址映射 */
     31 #define GPFCON  (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050)))
     32 #define GPFDAT  (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000054)))
     33 /* GPF引脚物理地址映射 */
     34 #define GPGCON  (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000060)))
     35 #define GPGDAT  (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000064)))
     36 
     37 
     38 static  int keys_open(struct inode *inode, struct file *filp)
     39 {
     40 
     41     /* 配置GPF0,2为输入引脚 */
     42     GPFCON &= ~(0x3 << (0 * 2) | 0x3 << (2 * 2));
     43     /* 配置GPG3,11为输入引脚 */
     44     GPGCON &= ~(0x3 << (3 * 2) | 0x3 << (11 * 2));
     45     return 0;
     46 }
     47 
     48 static int keys_close(struct inode *inode, struct file *filp)
     49 {
     50 
     51 
     52     return 0;
     53 }
     54 
     55 static ssize_t keys_read(struct file *filp, char __user *buff, size_t count, loff_t *oops)
     56 {
     57     /* 返回4个引脚的电平 */
     58     unsigned char key_vals[4];
     59     int regval;
     60 
     61     if (count != sizeof(key_vals))
     62         return -EIAVAL;
     63 
     64     /* 读GPF0,2 */
     65     regval = GPFDAT;
     66     key_vals[0] = (regval & (1 << 0)) ? 1 : 0;
     67     key_vals[1] = (regval & (1 << 2)) ? 1 : 0;
     68 
     69     /* 读GPG3,11 */
     70     regval = GPGDAT;
     71     key_vals[2] = (regval & (1 << 3)) ? 1 : 0;
     72     key_vals[3] = (regval & (1 << 12)) ? 1 : 0;
     73 
     74     copy_to_user(buf, key_val, sizeof(key_vals));
     75 
     76     return sizeof(key_vals);
     77     return 0;
     78 }
     79 
     80 static struct file_operations keys_fops = {
     81     .owner   =   THIS_MODULE,    /*  这是一个宏,指向编译模块时自动创建的__this_module变量 */
     82     .open    =   keys_open,
     83     .release =   keys_close, 
     84     .read    =   keys_read,
     85 };
     86 
     87 static int __init keys_init(void)
     88 {
     89     int ret;
     90     int minor;
     91 
     92     gpio_va = ioremap(0x56000000, 0x100000);//物理地址映射为虚拟地址,分配1M空间
     93     if (!gpio_va) 
     94         return -EIO;
     95 
     96     ret = register_chrdev(KEY_MAJOR, DEVICE_NAME, &key_fops);
     97     if(ret < 0)
     98     {
     99         printk(DEVICE_NAME " can't register major number
    ");
    100         return ret;
    101     }
    102 
    103     /* 设备类的创建 */
    104     keys_class = class_create(THIS_MODULE, DEVICE_NAME);
    105     if (IS_ERR(keys_class))
    106     {
    107         return PTR_ERR(keys_class);
    108     }
    109 
    110     for (minor = 0; minor < 4; minor++)
    111     {
    112         keys_class_dev[minor] = class_device_create(leds_class, NULL, MKDEV(KEY_MAJOR, minor), NULL, "key%d", minor);
    113         if (unlikely(IS_ERR(keys_class_dev[minor])))
    114             return PTR_ERR(keys_class_dev[minor]);
    115     }
    116 
    117     printk(DEVICE_NAME " initialized
    ");
    118     return 0;
    119 }
    120 
    121 static void __exit keys_exit(void)
    122 {
    123     int minor;
    124     for (minor = 0; minor < 4; minor++)
    125     {
    126         class_device_unregister(keys_class_dev[minor]);
    127     }
    128     class_destroy(keys_class);
    129     unregister_chrdev(KEY_MAJOR, DEVICE_NAME);
    130     iounmap(gpio_va);
    131 }
    132 
    133 module_init(keys_init);
    134 module_exit(keys_exit);
    135 MODULE_LICENSE("Dual BSD/GPL");  
    View Code

      2.2 测试代码

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 #include <sys/ioctl.h>
     5 
     6 int main(void)
     7 {
     8     int fd;
     9     unsigned char key_vals[4];
    10     int cnt = 0;
    11 
    12     fd = open("/dev/keys", O_RDWR);
    13     if (fd < 0)
    14     {
    15         printf("can't open!!!
    ");
    16 
    17         while (1)
    18         {
    19             read(fd, key_vals, sizeof(key_vals));
    20             if (!key_vals[0] || !key_vals[1] || !key_vals[2] || !key_vals[3])
    21             {
    22                 printf("%04d key pressed: %d %d %d %d
    ", cnt++, key_vals[0], key_vals[1], key_vals[2], key_vals[3]);
    23             }
    24         }
    25     }
    26 
    27     return 0;
    28 }
    View Code

     

      

      

    ---恢复内容结束---

  • 相关阅读:
    关于MySql中的varchar类型
    分享15个HTML5工具
    MVC的路径查找顺序
    html5画布的旋转效果
    C#将集合快速排序
    一个不错的php验证码的类
    新学C++的for,switch和随机数
    高效率去掉js数组中重复项
    js带上框架和防止被iframe的代码
    请不要对我说“你要马上把这个小问题修改好”
  • 原文地址:https://www.cnblogs.com/kele-dad/p/6902676.html
Copyright © 2020-2023  润新知