Linux驱动程序开发之三----按键驱动(Tiny6410)

2023-05-16

Linux驱动程序开发之三----按键驱动(Tiny6410)博文中讨论了使用中断来实现按键驱动,毫无疑问,中断方式效率相当高,但是在此之前,CPU要想获知按键的状态都是通过查询方式来实现的,查询方式就是CPU不停的检查按键的状态,如果有变化则立即输出,而中断是外设向CPU传递消息,告诉CPU自己状态改变了,要求CPU进行处理,而其他时间CPU可以做自己想做的事情,和微机原理以及操作系统课程中讲的一样,代码实现如下:

首先编写驱动框架,然后配置KEY值的GPIO管脚为输入,然后实现read函数,在read函数中读取KEY值,并拷贝到用户空间,用户程序则不停的读取按键的状态,如果变低则输出一条消息,否则不输出。Tiny6410中按键的电路图如下:


当未按下时,K1~K8为高电平,当按下后为低电平。

按键对应GPIO
KEYGPIO管脚
KEY1GPN0
KEY2GPN1
KEY3GPN2
KEY4GPN3
KEY5GPN4
KEY6GPN5
KEY7GPL11
KEY8GPL12
详细代码如下:

[cpp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <linux/module.h>//MODULE_LICENSE,MODULE_AUTHOR  
  2. #include <linux/init.h>//module_init/module_exit  
  3.   
  4.   
  5. #include <linux/fs.h>//file_operations  
  6. #include <asm/io.h>//ioread32,iowrite32  
  7. #include <linux/cdev.h>//cdev  
  8. #include <mach/map.h>//定义了S3C64XX_VA_GPIO  
  9. #include <mach/regs-gpio.h>//定义了gpio-bank-n中使用的S3C64XX_GPN_BASE  
  10. #include <mach/gpio-bank-n.h>//定义了GPNCON  
  11. #include <mach/gpio-bank-l.h>//定义了GPNCON  
  12. #include <linux/wait.h>//wait_event_interruptible(wait_queue_head_t q,int condition);  
  13. //wake_up_interruptible(struct wait_queue **q)  
  14. #include <linux/sched.h>//request_irq,free_irq  
  15. #include <asm/uaccess.h>//copy_to_user  
  16. #include <linux/irq.h>//IRQ_TYPE_EDGE_FALLING  
  17. #include <linux/interrupt.h>//request_irq,free_irq  
  18. #include <linux/device.h>//class device  
  19. MODULE_AUTHOR("jefby");  
  20. MODULE_LICENSE("Dual BSD/GPL");  
  21. MODULE_DESCRIPTION("Tiny 6410 buttons with search");  
  22.   
  23. #define GPNCON 0x7F008830  
  24. #define GPLCON0 0x7F008810  
  25.   
  26. static volatile unsigned int * gpncon = NULL;  
  27. static volatile unsigned int * gpndat = NULL;  
  28. static volatile unsigned int * gplcon = NULL;  
  29. static volatile unsigned int * gpldat = NULL;  
  30. //按键设备的主设备号  
  31. static int buttons_major = 0;  
  32. //设备号  
  33. dev_t dev;  
  34. //字符设备  
  35. struct cdev * buttons_cdev;  
  36.   
  37. static struct class * tiny6410_buttons_class = NULL;  
  38. static struct device * tiny6410_buttons_device = NULL;  
  39.   
  40.   
  41. //设备打开操作,主要完成BUTTONS所对应的GPIO的初始化,注册用户中断处理函数  
  42. int  buttons_open(struct inode *inode,struct file *filp)  
  43. {  
  44.     unsigned val;  
  45.   
  46.     /*设置buttons对应的GPIO管脚,设置KEY1~KEY6*/  
  47.     gpncon = (volatile unsigned int*)ioremap(GPNCON,16);  
  48.     gpndat = gpncon + 1;  
  49.     val = ioread32(gpncon);//读取GPNCON的值  
  50.     val = (val & ~(0xFFF));//设置GPIO 0~5为输入  
  51.     iowrite32(val,gpncon);  
  52.   
  53.     //设置KEY7,KEY8为输入,gpl11,gpl12  
  54.     gplcon = (volatile unsigned int*)ioremap(GPLCON0,16);  
  55.     gpldat = gplcon + 2;//gpldat  
  56.     val = ioread32(gplcon+1);//读取GPNCON1的值  
  57.     val = (val & ~(0xFF<<12));//设置GPL11和12为输入  
  58.     iowrite32(val,gplcon+1);  
  59.   
  60. /* 
  61.     val = ioread32(S3C64XX_GPLCON1); 
  62.     val = (val & ~(0xFF<<12)) | (0x33); 
  63.     iowrite32(val,S3C64XX_GPLCON1); 
  64. */  
  65.     printk("buttons open.\n");  
  66.     return 0;  
  67. }  
  68. //按键读若没有键被按下,则使进程休眠;若有按键被按下,则拷贝数据到用户空间,然后清零  
  69. int buttons_read(struct file *filp, char __user *buf, size_t len, loff_t * pos)  
  70. {  
  71.     unsigned char keyval[8]={0};  
  72.     unsigned int temp=0;  
  73.     int i=0;  
  74.     if(len != 8)  
  75.         return -1;  
  76.     temp=ioread32(gpndat);  
  77.     //读取KEY1~KEY6的值  
  78.     for(i=0;i<6;++i){  
  79.         keyval[i] = (temp&(0x1<<i))?1 : 0;  
  80.     }  
  81.     temp = ioread32(gpldat);  
  82.     //读取KEY7和KEY8的值  
  83.     keyval[6]=(temp&(0x1<<11))?1:0;  
  84.     keyval[7]=(temp&(0x1<<12))?1:0;  
  85.     copy_to_user(buf,keyval,sizeof(keyval));  
  86.   
  87.     return 0;  
  88.   
  89. }  
  90. //主要是卸载用户中断处理程序  
  91. int buttons_close(struct inode *inode,struct file *filp)  
  92. {  
  93.     printk("buttons close.\n");  
  94.     return 0;  
  95. }  
  96.   
  97.   
  98. static struct file_operations buttons_fops = {  
  99.     .owner = THIS_MODULE,  
  100.     .read = buttons_read,  
  101.     .release = buttons_close,  
  102.     .open = buttons_open,  
  103. };  
  104. /* 
  105.     模块初始化: 
  106.         1.申请设备号,默认使用动态分配的方法 
  107.         2.申请并初始化cdev结构 
  108.         3.将cdev注册到内核 
  109. */  
  110. static int module_buttons_init(void)  
  111. {  
  112.     int err=0;  
  113.     int result=0;  
  114.     printk("Tiny6410 buttons module init.\n");    
  115.     if(buttons_major){  
  116.         dev = MKDEV(buttons_major,0);  
  117.         result = register_chrdev_region(dev,1,"buttons");  
  118.     }else{  
  119.         result = alloc_chrdev_region(&dev,0,1,"buttons");  
  120.         buttons_major = MAJOR(dev);  
  121.     }  
  122.     if(result < 0){  
  123.         printk(KERN_WARNING "buttons : can't get major %d\n",buttons_major);  
  124.     }  
  125.   
  126.     printk("buttons major is %d",buttons_major);  
  127.     buttons_cdev = cdev_alloc();  
  128.     buttons_cdev ->ops = &buttons_fops;  
  129.     cdev_init(buttons_cdev,&buttons_fops);  
  130.     cdev_add(buttons_cdev,dev,1);  
  131.   
  132.     tiny6410_buttons_class = class_create(THIS_MODULE, "tiny6410buttons");  
  133.     if (IS_ERR(tiny6410_buttons_class)) {  
  134.         err = PTR_ERR(tiny6410_buttons_class);  
  135.         printk("create class error.\n");  
  136.     }  
  137.     tiny6410_buttons_device = device_create(tiny6410_buttons_class, NULL, MKDEV(buttons_major, 0), NULL,  
  138.                   "buttons");  
  139.     printk("buttons add ok.\n");  
  140.     return 0;  
  141. }  
  142.   
  143. static void module_buttons_exit(void)  
  144. {  
  145.     iounmap(gpncon);  
  146.     device_destroy(tiny6410_buttons_class, MKDEV(buttons_major, 0));  
  147.     class_destroy(tiny6410_buttons_class);  
  148.     cdev_del(buttons_cdev);  
  149.     unregister_chrdev_region(dev,1);  
  150.     printk("Tiny6410 buttons module exit");  
  151. }  
  152.   
  153. module_init(module_buttons_init);  
  154. module_exit(module_buttons_exit);  

用户程序的代码如下:

[cpp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <sys/ioctl.h>  
  5.   
  6.   
  7. int main(int argc,char **argv)  
  8. {  
  9.     int i;  
  10.     int ret;  
  11.     int fd;  
  12.     unsigned char keyval[8]={1,1,1,1,1,1,1,1};  
  13.     static int cnt = 0;  
  14.   
  15.     //打开设备  
  16.     fd = open("/dev/buttons",0);  
  17.     if(fd < 0){  
  18.         printf("can't open /dev/buttons\n");  
  19.         return -1;  
  20.     }  
  21.     while(1){  
  22.         for(i=0;i<8;++i){  
  23.             ret = read(fd,keyval,sizeof(keyval));  
  24.             if(ret < 0){  
  25.                 printf("read err.\n");  
  26.                 return -1;  
  27.             }  
  28.             if(keyval[i] == 0){  
  29.                 printf("%d:KEY%d entered.\n",cnt++,i+1);  
  30.             }  
  31.         }//for  
  32.     }//while(1)  
  33.     close(fd);  
  34.     return 0;  
  35. }  

运行截图如下:


可以看出每按下一次就会打印出一串消息,说明那个按键被按下。使用top命令查看当前的CPU使用率,截图如下:可以看出,查询方式下确实效率太低了,CPU被占用了90%多以上

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux驱动程序开发之三----按键驱动(Tiny6410) 的相关文章

  • 跟踪 Linux 程序中活跃使用的内存

    我想跟踪各种程序在特定状态下接触了多少内存 例如 假设我有一个图形程序 最小化时 它可能会使用更少的内存 因为它不会重新绘制窗口 这需要读取图像和字体并执行大量库函数 这些对象仍然可以在内存中访问 但实际上并没有被使用 类似的工具top它们
  • 通过特定分隔符删除字符串

    我的文件中有几列 其中第二列有 分隔符 我想删除第二列中的第一个 第三个和第四个字符串 并将第二个字符串留在该列中 但我有正常的分隔符空间 所以我不知道 input 22 16050075 A G 16050075 A G 22 16050
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • Linux中的CONFIG_OF是什么?

    我看到它在很多地方被广泛使用 但不明白在什么场景下我需要使用它 What is 配置 OF OF 的全名是什么 打开固件 这是很久以前发明的 当时苹果公司正在生产基于 PowerPC CPU 的笔记本电脑 而 Sun Microsystem
  • 大多数 Linux 系统头文件与 C++ 兼容吗?

    大多数 Linux 系统头文件 API C 兼容吗 今天我试图做这样的事情 include
  • 我可以从命令行打印 html 文件(带有图像、css)吗?

    我想从脚本中打印带有图像的样式化 html 页面 谁能建议一个开源解决方案 我使用的是 Linux Ubuntu 8 04 但也对其他操作系统的解决方案感兴趣 你可以给html2ps http user it uu se jan html2
  • Linux中的定时器类

    我需要一个计时器来以相对较低的分辨率执行回调 在 Linux 中实现此类 C 计时器类的最佳方法是什么 有我可以使用的库吗 如果您在框架 Glib Qt Wx 内编写 那么您已经拥有一个具有定时回调功能的事件循环 我认为情况并非如此 如果您
  • 在哪里可以找到并安装 pygame 的依赖项?

    我对 Linux 比较陌生 正在尝试安装 python 的 pygame 开发环境 当我运行 setup py 时 它说我需要安装以下依赖项 我找到并安装了其中之一 SDL 然而 其他人则更加难以捉摸 Hunting dependencie
  • 加载数据infile,Windows和Linux的区别

    我有一个需要导入到 MySQL 表的文件 这是我的命令 LOAD DATA LOCAL INFILE C test csv INTO TABLE logs fields terminated by LINES terminated BY n
  • 如何在数组中存储包含双引号的命令参数?

    我有一个 Bash 脚本 它生成 存储和修改数组中的值 这些值稍后用作命令的参数 对于 MCVE 我想到了任意命令bash c echo 0 0 echo 1 1 这解释了我的问题 我将用两个参数调用我的命令 option1 without
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im
  • PHP 从命令行启动 gui 程序,但 apache 不启动

    首先 我阅读了有类似问题的人的一些帖子 但所有答案都没有超出导出 DISPLAY 0 0 和 xauth cookies 这是我的问题 提前感谢您的宝贵时间 我开发了一个小库 它使用 OpenGL 和 GLSL 渲染货架 过去几天我将它包装
  • Linux 内核标识符中前导和尾随下划线的含义是什么?

    我不断遇到一些小约定 比如 KERNEL Are the 在这种情况下 是内核开发人员使用的命名约定 还是以这种方式命名宏的语法特定原因 整个代码中有很多这样的例子 例如 某些函数和变量以 甚至 这有什么具体原因吗 它似乎被广泛使用 我只需
  • 将 PDF 转换为 600dpi 的 TIFF 和 jpg 96 dpi

    我想使用 ImageMagick 从 Python 脚本将 pdf 转换为 600 dpi 的 tiff 和 96 dpi 的 jpg 我使用 imagemagick 命令行完成了这项任务 但我想使用python中的Imagemagick将
  • NPTL 和 POSIX 线程有什么区别?

    NPTL 和 POSIX 线程之间的基本区别是什么 这两者是如何演变的 POSIX 线程 pthread 不是一个实现 它是几个函数的 API 规范 纸上的标准 英文 其名称以pthread 以及定义在
  • 如何在apache 2.4.6上安装apxs模块

    我刚刚用过apt get update我的 apache 已更新为2 4 6 我想安装 apxs 来编译模块 但收到此错误 The following packages have unmet dependencies apache2 pre
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的
  • Linux 中什么处理 ping?

    我想覆盖 更改 linux 处理 ping icmp echo 请求数据包的方式 这意味着我想运行自己的服务器来回复传入的 icmp 回显请求或其他 数据包 但为了使其正常工作 我想我需要禁用 Linux 的默认 ping icmp 数据包
  • jq中如何分组?

    这是 json 文档 name bucket1 clusterName cluster1 name bucket2 clusterName cluster1 name bucket3 clusterName cluster2 name bu

随机推荐

  • Java基础(五):重写toString()方法

    目录 1 Object 类的 toString 2 重写toString 方法意义 3 总结 1 Object 类的 toString Java默认的toString方法来自Object类 在Java中每个类都直接或者间接继承Object类
  • Mysql基础(十九):锁

    目录 1 Mysql锁机制 1 1 乐观锁和悲观锁 1 1 1 乐观锁 1 1 2 悲观锁 1 2 共享锁与排他锁 1 2 1 共享锁 1 2 2 排他锁 1 3 行锁与表锁 1 3 1 行锁 1 3 2 表锁 1 4 间隙锁 1 4 1
  • 大数据时代的图表可视化利器——highcharts,D3和百度的echarts

    还记得阿里巴巴那个令人澎湃激情的双十一吗 xff1f 还记得淘宝生动形象地把你的的消费历程一一地展示给你看吗 xff1f 还记得那些酷炫拽的it报告图表吗 xff1f 在这个大数据越来越盛行的年代 xff0c 怎样去表达一些用户的关系 xf
  • 对三层和MVC的认识过程

    三层架构就是 MVC xff01 起初老师总说三层 MVC xff0c MVC 三层架构 所以开始的时候脑子就一个概念 xff1a 三层就是 MVC xff0c MVC 就是三层架构 而且想想也合理啊 xff0c 都是 三 MVC 是三个字
  • ROS雷达包出现:ERROR: cannot launch node of type: rplidar_ros

    ROS雷达包出现 xff1a ERROR cannot launch node of type rplidar ros 问题分析详情 问题分析 仅安装了基础ROS xff0c rplidar ros包没有安装 详情 下载包并解压缩 1 使用
  • nvidia-smi出现的比较慢

    一个比较老的问题 xff0c 一般四卡以上的机器可能会出现 以前我都是 nvidia span class hljs attribute smi span span class hljs attribute pm span span cla
  • 【tensorflow】tensorflow的安装及应用

    安装tensorflow的三种方法 1 在cmd命令行中输入pip install tensorflow xff0c 默认安装最新版 2 其他旧版本的安装 xff0c 去pypi org官网 可以点击release history选择想要的
  • 汇编:stmdb和ldmia指令

    参考了网上一些文章 xff0c 简单说一下stmdb和ldmia指令的作用 xff0c 如有错误欢迎指正 首先一句话说一下stmdb和ldmia指令 的作用 xff1a stmdb和ldmia指令一般配对使用 xff0c stmdb用于将寄
  • ARM 内联汇编 加速 算法

    首推移动端arm cpu优化学习笔记第4弹 内联汇编入门 xff0c 但是其只给出了代码 xff0c 很多人还不知道怎么在手机上跑起来 xff0c 其实只需要一个CMakeLists txt就可以了 cmake minimum requir
  • centos7.3环境编译安装pktgen-dpdk,dpdk工具

    概述编译环境编译DPDK编译Pktgen dpdkDebug 概述 DPDK xff08 Date Plane Development Kit xff09 主要基于Linux系统运行 xff0c 用于快速数据包处理的函数库与驱动集合 xff
  • 捷联惯导算法心得

    1 四个概念 xff1a 地理 坐标系 机体 坐标系 他们之间换算公式 换算公式用的系数 地理坐标系 xff1a 东 北 天 xff0c 以下简称 地理 在这个坐标系里有重力永远是 xff08 0 0 1g xff09 xff0c 地磁永远
  • Java中的域,静态域,实例域

    域 所谓的域 xff0c 是field的翻译 xff0c 也就是我们常说的字段 xff0c 或者属性 比如类的字段 xff08 属性 xff09 xff0c 局部的 xff0c 全局的 静态域 也就是静态属性 xff0c 我们可以单独为它设
  • 【线程篇】线程间同步之信号量、互斥锁

    线程 xff1a 进程内部的一条执行路径 xff08 序列 xff09 什么是线程什么是进程 xff0c 进程和线程的区别 xff1f 进程是一个正在运行的程序 xff0c 是系统进程资源分配的基本单位 线程是进程内部的一条执行路径 xff
  • PL/SQL报错:无法解析指定的连接标识符

    在安装oracle的时候PL SQL报错 xff1a ORA 12154 TNS 无法解析指定的连接标识符 xff0c 在网上找了很多资料 xff0c 然后问题解决 其中下面的文章分析的过程很值得学习 xff0c 特地转载过来时刻告诫自己全
  • 【idm】idm突破cookie封锁 (解决http:1.1 403 forbidden)(附charles使用教程)

    文章目录 一 问题二 解决方法 xff08 1 xff09 在chrome中获得cookies xff08 2 xff09 安装配置charles 三 另外的方法参考 idm的使用教程参考 xff1a 一 问题 使用idm下载文件出现如下问
  • 四旋翼飞行器数学建模+轨迹跟踪控制

    数学模型 xff08 状态空间方程 xff09 xff1a 控制算法 有限时间 xff08 finite time control xff09 控制 xff0c 文献 1 xff1b 比例 微分 xff08 PD xff09 控制 xff0
  • 卡尔曼滤波算法总结

    自己学习整理卡尔曼滤波算法 xff0c 从放弃到精通 kaerman 滤波算法 卡尔曼滤波是非常经典的预测追踪算法 xff0c 是结合线性系统动态方程的维纳滤波 xff0c 其实质是线性最小均方差估计器 xff0c 能够在系统存在噪声和干扰
  • 做嵌入式驱动的前途何在

    做嵌入式驱动的前途何在 做嵌入式linux驱动的前途何在 xff1f 或者说 xff0c 怎么才能做好这一行 xff1f 我做嵌入式驱动开发已经一年多了 xff0c 感觉没学到多少东西 从网络驱动到CAN驱动 从dataflash驱动到NA
  • 串口通信的调试01

    在开发中 xff0c 我们经常遇到这种情况 xff0c 供应商给了一台仪器 xff0c 然后仪器配套有软件 我们通过点击按钮往仪器发送命令 xff0c 仪器返回数据 有些时候 xff0c 我们希望可以通过自己编写的软件来操作仪器 xff0c
  • Linux驱动程序开发之三----按键驱动(Tiny6410)

    在Linux驱动程序开发之三 按键驱动 xff08 Tiny6410 xff09 博文中讨论了使用中断来实现按键驱动 xff0c 毫无疑问 xff0c 中断方式效率相当高 xff0c 但是在此之前 xff0c CPU要想获知按键的状态都是通