arm6410按键驱动程序

来源:互联网 发布:云房数据这公司怎么样 编辑:程序博客网 时间:2024/05/21 13:23
arm6410按键驱动程序
通过查询的方法获取按键值
驱动程序  botton_drive.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/device.h>
//#include <asm/arch/regs-gpio.h>
//#include <asm/hardware.h>

static struct class *seconddrv_class;
static struct class_device*seconddrv_class_dev;

volatile unsigned long *gpmcon = NULL;
volatile unsigned long *gpmdat = NULL;
volatile unsigned long *gpncon = NULL;
volatile unsigned long *gpndat = NULL;


static int second_drv_open(struct inode *inode, struct file *file)
{
//printk("second_drv_open\n");
/* 配置GPm0,1,2,3为输出 */
*gpmcon &= ~((0xf<<(4*0)) | (0xf<<(4*1)) | (0xf<<(4*2)) | (0xf<<(4*3)));
*gpmcon |=  ((0x1<<(4*0)) | (0x1<<(4*1)) | (0x1<<(4*2)) | (0x1<<(4*3)));
/* 配置GPn0,1,2,3,4,5为输入 */
*gpncon &= ~((0x3<<(2*0)) | (0x3<<(2*1)) | (0x3<<(2*2)) | (0x3<<(2*3)) | (0x3<<(2*4)) | (0x3<<(2*5)));
//*gpncon |=  ((0xf<<(4*0)) | (0xf<<(4*1)) | (0xf<<(4*2)) | (0xf<<(4*3)) | (0xf<<(4*4)) | (0xf<<(4*5)));
return 0;
}

static ssize_t second_drv_read(struct file *file, const char __user *buf, size_t size, loff_t * ppos)
{
unsigned char KEY_val[6];
if(size != sizeof(KEY_val))
return -EINVAL;
int regval;
regval = *gpndat;

/* 读出个个引脚的状态 */
KEY_val[0] = (regval & 1<<0) ? 1:0;
KEY_val[1] = (regval & 1<<1) ? 1:0;
KEY_val[2] = (regval & 1<<2) ? 1:0;
KEY_val[3] = (regval & 1<<3) ? 1:0;
KEY_val[4] = (regval & 1<<4) ? 1:0;
KEY_val[5] = (regval & 1<<5) ? 1:0;

/* 传递给用户 */
copy_to_user(buf, KEY_val, sizeof(KEY_val));

return sizeof(KEY_val);
}

static struct file_operations second_drv_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   second_drv_open,     
.read= second_drv_read,   
};


int major;
static int second_drv_init(void)
{
//printk(KERN_ERR "second_drv_init\n");
major = register_chrdev(0, "secondt_drv", &second_drv_fops); // 注册, 告诉内核

seconddrv_class = class_create(THIS_MODULE, "seconddrv");

seconddrv_class_dev = device_create(seconddrv_class, NULL, MKDEV(major, 0), NULL, "bottons"); /* /dev/bottons */

gpmcon = (volatile unsigned long *)ioremap(0x7F008820, 16);
gpmdat = gpmcon + 1;
gpncon = (volatile unsigned long *)ioremap(0x7F008830, 16);
gpndat = gpncon + 1;

return 0;
}

static void second_drv_exit(void)
{
//printk(KERN_ERR "second_drv_exit\n");
unregister_chrdev(major, "second_drv"); // 卸载

device_unregister(seconddrv_class_dev);
class_destroy(seconddrv_class);
iounmap(gpmcon);
iounmap(gpncon);
}

module_init(second_drv_init);
module_exit(second_drv_exit);


MODULE_LICENSE("GPL");

测试程序botton_test.c

 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

/* botton test
  * 
  */
int main(int argc, char **argv)
{
int fd;
int cnt = 0;
unsigned char key_vals[6];
fd = open("/dev/bottons", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}

while (1)
{
read(fd, key_vals, sizeof(key_vals));
if (!key_vals[0] || !key_vals[1] || !key_vals[2] || !key_vals[3] || !key_vals[4] || !key_vals[5])
{
printf("%d key pressed %d %d %d %d %d %d\n", cnt++, key_vals[0], key_vals[1], key_vals[2], 
key_vals[3], key_vals[4], key_vals[5]);
}
}
return 0;
}

加载驱动 
图片

测试
 图片
当按下一个按键
图片
有好几百个这样的输出 原因是没有加上去抖程序
后台运行
 图片
top 查看任务管理器 
 图片
一个按键程序占用了 99.6% 的CPU 太疯狂了 原因是通过查询的方式获取按键值  程序是一个死循环 
 图片
下一步通过中断的方式获取按键值
杀死进程
图片
原创粉丝点击