字符设备程序实列二-查询按键值,按键按下相应的LED灯亮,按键松开相应的LED灯灭
来源:互联网 发布:网络音视频许可证 编辑:程序博客网 时间:2024/05/20 22:29
按照实例一,实现了从应用程序空间向内核空间传递数据,这一例实现从内核读取按键值到应用空间,然后把刚刚保存在应用空间按键值写到内核空间,内核空间按键值来操作对应的LED
驱动源码:keys_leds.c
驱动源码Makefile
测试源码: keys_leds_test.c
keys_leds.c:
/***************************************************************
*filename:keys_leds.c*description:无按键按下,熄灭全部LED,按键按下,点亮相应LED,松开熄灭相应LED*author:xyc*create time:2014/6/2*version:1*modify info:******************************************************/#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/irq.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#include <asm-arm/io.h>#include <asm-arm/uaccess.h>static int KEYS_LEDS_MAJOR;static struct class *keys_leds;static struct class_device *keys_leds_dev;static volatile unsigned long *gpfcon=NULL;static volatile unsigned long *gpfdat=NULL;static int keys_leds_open(struct inode *inode, struct file *file){/*配置按键为输入,LED为输出*/*gpfcon &= ~(0x3<<(4*2)) & (~(0x3<<(0*2))) & (~(0x3<<(5*2)) ) & (~(0x3<<(2*2)));*gpfcon |= 0x1<<(4*2) |(0x0<<(0*2)) | (0x1<<(5*2) )|(0x0<<(2*2));*gpfdat |=1<<4|1<<5;return 0;}static ssize_t keys_leds_read(struct file *file, char __user *userbuf, size_t count, loff_t *off){char val =0;//初始化为0不要忘/*记录按下的键*/if( !(*gpfdat & (1<<0)) ){/*s2按下*/val =1;} if (!(*gpfdat & (1<<2))){/*s3按下*/val =2;}copy_to_user(userbuf, &val, 1);return 1;}static ssize_t keys_leds_write(struct file * file, const char __user * userbuf, size_t count, loff_t * off){char val=0; //初始化为0,不要忘/* *按键没按下keys_leds_read传给应用read的按键值为0, *应用write将按键值0传给 keys_leds_write的val,LED均熄灭 */ /* *按键按下,keys_leds_read传给应用read的按键值为1或2, *应用write将按键值1或2传给 keys_leds_write的val相应的LED亮 */copy_from_user(&val, userbuf, 1);switch(val){case 1:{/*点亮LED4*/*gpfdat &=~(1<<4);break;}case 2:{/*点亮LED5*/*gpfdat &=~(1<<5);break;}default:{/*俩个按键均没按下,此时read()读到的值为0,*再将0写入到驱动keys_leds_write()函数的自动变量val*/*gpfdat |= (1<<4)|(1<<5); //不要忘记没按键或按键松开时灭灯break;}}}static struct file_operations keys_leds_op = {.owner = THIS_MODULE,.open= keys_leds_open,.read= keys_leds_read,.write= keys_leds_write,};static int __init keys_leds_init(){int minor;KEYS_LEDS_MAJOR = register_chrdev(0, "keys_leds", &keys_leds_op);if(KEYS_LEDS_MAJOR <0){printk("register char device failed\n");return KEYS_LEDS_MAJOR;}keys_leds = class_create(THIS_MODULE, "keys_leds");keys_leds_dev =class_device_create(keys_leds, NULL, MKDEV(KEYS_LEDS_MAJOR, 0), NULL, "leds");gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);gpfdat = gpfcon +1;return 0;}static void __exit keys_leds_exit(){unregister_chrdev(KEYS_LEDS_MAJOR, keys_leds);class_device_destroy(keys_leds, MKDEV(KEYS_LEDS_MAJOR, 0));class_destroy(keys_leds);iounmap(gpfcon);}module_init(keys_leds_init);module_exit(keys_leds_exit);MODULE_LICENSE("GPL");
程序编写过程中,编译出现的错误:
1.keys_leds_op后面忘掉等号,2.将按键驱动分为几个设备节点,没编译之前发现,但static struct class_device *keys_leds_dev[3]没有改过来3.头文件不记得写了
4.keys_leds_read/keys_leds_write中val忘记初始化为0,keys_leds_write对val = 0即没有按键按下或按键松开时进行灭灯处理
Makefile:
跟实例一差不多
KERN_DIR = /work/system/linux-2.6.22.6all:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m+= keys_leds.o
这里obj-m表示以模块动态加载的方式启用,并没有编入内核,所以开发板断电重启后,断电前的模块已经卸载掉了,同理对应的在模块中创建的设备文件也不存在了
测试模块keys_leds_test.c:
/****************************************************************filename:keys_leds_test.c*description:测试keys_leds.c驱动*author:xyc*create time:2014/6/2*version:1*modify info:****************************************************************/#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>int main(int argc, char *argv[]){int fd1;char key_value=0;if(argc !=2 ){ printf("Usage:\n"); printf("%s <dev> <on|off>\n",argv[0]); printf("eg. \n"); printf("%s /dev/leds \n", argv[0]); return -1;}fd1 = open(argv[1], O_RDWR);if( fd1<0){printf("%s open failed", argv[1]);return -1;}while(1){read(fd1, &key_value, 1);if( (key_value==1) |(key_value==2) ) write(fd1, &key_value, 1);else write(fd1, &key_value, 1);}close(fd1);return 0;}
#include <stdio.h>#include <fcntl.h>#include <unistd.h>这3个头文件,导致O_RDWR未定义,此时因为O_RDWR是open使用的,这时在ubuntu下man 2 open看其需要包含的头文件为
#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>
所以加上
#include <sys/types.h>#include <sys/stat.h>
这2头文件O_RDWR的编译错误就消失了
还有可能忘了的对key_value==1或2调用的write将按键值传给内核空间,但没按下时的按键值key_value==0没调用write即没把无按键按下的值传给内核空间,导致松开按键后,LED灯不熄灭,因为程序不断read ->第一个write写1或2->read->第一个write写1或2... 在第一个write写1或2都是点亮LED4 或LED5,这样按下S2 LED4,LED4亮,松开S2 LED4不灭,所以需要对驱动没有读到按键值时在测试程序中做判断,然后将无按键的值0传给驱动keys_leds_write中的临时变量val使得在switch(0)中关掉LED4 LED5
,
测试看按键按下,相应的LED灯是否亮,松开,相应的LED灯黑,同时按下的反应
本驱动代码因为是在测试代码中轮询按键,所以CPU占用率几乎达到了100%,所以实用中均是用的中断方式
Mem: 6696K used, 54488K free, 0K shrd, 0K buff, 2068K cachedCPU: 8% usr 91% sys 0% nice 0% idle 0% io 0% irq 0% softirqLoad average: 0.99 0.96 0.84 PID PPID USER STAT VSZ %MEM %CPU COMMAND 793 770 0 R 1308 2% 99% ./keys_leds_test /dev/leds 806 770 0 R 3096 5% 0% top 770 1 0 S 3096 5% 0% -sh 1 0 0 S 3092 5% 0% init 762 2 0 SW< 0 0% 0% [rpciod/0] 6 2 0 SW< 0 0% 0% [khelper] 745 2 0 SW< 0 0% 0% [kmmcd] 2 0 0 SW< 0 0% 0% [kthreadd] 3 2 0 SWN 0 0% 0% [ksoftirqd/0] 4 2 0 SW< 0 0% 0% [watchdog/0] 5 2 0 SW< 0 0% 0% [events/0] 55 2 0 SW< 0 0% 0% [kblockd/0] 56 2 0 SW< 0 0% 0% [ksuspend_usbd] 59 2 0 SW< 0 0% 0% [khubd] 61 2 0 SW< 0 0% 0% [kseriod] 73 2 0 SW 0 0% 0% [pdflush] 74 2 0 SW 0 0% 0% [pdflush] 75 2 0 SW< 0 0% 0% [kswapd0] 76 2 0 SW< 0 0% 0% [aio/0]nfs: server 192.168.1.19 not responding, still trying
0 0
- 字符设备程序实列二-查询按键值,按键按下相应的LED灯亮,按键松开相应的LED灯灭
- 国嵌实验:key_poll,采用查询的方式一旦按键再松开,LED亮灭一次
- 用遥控器控制led灯亮以及LCD上显示相应的按键数
- Linux button按键驱动 多次中断控制相应LED灯亮灭闪
- 简单的按键控制LED
- 按键支持连续按的相应代码
- 按键+Led
- 按键-LED
- 4.1.按键--按下按键使LED点亮
- TQ2440 查询法实现按键LED的功能
- ARM开发板mini2440的按键控制LED小程序
- 黑苹果键盘对应的相应按键
- 按键控制Led的裸奔代码
- 将键盘的按键转换成相应的Unicode 值
- 按键实现led
- ARM9---LED和按键
- 按键 led灯实验
- 按键控制led
- Hi3520D SDK 安装以及升级使用说明
- jsoup的基础理论(一)
- POJ 1322 Chocolate
- Windows7 64位和32位有何差异
- POJ 3827 Facer is learning to swim
- 字符设备程序实列二-查询按键值,按键按下相应的LED灯亮,按键松开相应的LED灯灭
- java.util.concurrent包(1)-lock和synchronized对比
- LeetCode —— Sort List
- 虚基类--动物学。。。。
- USB mass storage framework
- NYOJ-60 谁获得了最高奖学金
- Oracle操作XML各种场景介绍
- 用antlr4来实现《按编译原理的思路设计的一个计算器》中的计算器
- 条款16:成对使用new和delete时要采取相同形式