⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buttons.c

📁 linux下的矩阵式键盘驱动ppt教程与源码实例!
💻 C
字号:
#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <linux/delay.h>#include <asm/hardware.h>#include <asm/irq.h>#define DEVICE_NAME "buttons"#define BUTTON_MAJOR 232/*********************************************************        4X4 矩阵键盘四个输入引脚:  	EINT0 -----( GPF0  )----INPUT                    EINT2 -----( GPF2  )----INPUT                    EINT11-----( GPG3  )----INPUT                    EINT19-----( GPG11 )----INPUT                                                                                                                                               四个输出引脚:  	KEYSCAN0---( GPE11 )----OUTPUT                    KEYSCAN1---( GPG6  )----OUTPUT                    KEYSCAN2---( GPE13 )----OUTPUT                    KEYSCAN3---( GPG2  )----OUTPUT**********************************************************//*int Key_Scan( void ){	int returnvalue;//delay//	unsigned long j = jiffies +5;//	while(jiffies<j);//上锁spin_lock_irq (&my_lock);	GPGCON = GPGCON & (~((3<<22)|(3<<6))) | ((0<<22)|(0<<6)) ;            //GPG11,13 set input        GPFCON = GPFCON & (~((3<<4)|(3<<0))) | ((0<<4)|(0<<0)) ;              //GPF2,0 set input        //扫描键盘第4列 K16、K15、K14、K13        GPGDAT = GPGDAT & (~((1<<6)|(1<<2))) | (1<<6) | (0<<2) ;                      //GPG6 output 1;GPG2 output 0        GPEDAT = GPEDAT & (~((1<<13)|(1<<11))) | (1<<13) | (1<<11) ;          //GPE13 output 1;GPE11 output 1        if(      (GPFDAT&(1<< 0)) == 0 )              { returnvalue= 16 ;goto out;}        else if( (GPFDAT&(1<< 2)) == 0 )              { returnvalue= 15 ;goto out;}        else if( (GPGDAT&(1<< 3)) == 0 )              { returnvalue= 14 ;goto out;}        else if( (GPGDAT&(1<<11)) == 0 )              { returnvalue= 13 ;goto out;}                                                                                                                                                       //扫描键盘第2列 K11、K8、K5、K2        GPGDAT = GPGDAT & (~((1<<6)|(1<<2))) | (0<<6) | (1<<2) ;                  //GPG6 output 0;GPG2 output 1        GPEDAT = GPEDAT & (~((1<<13)|(1<<11))) | (1<<13) | (1<<11) ;          //GPE13 output 1;GPE11 output 1        if(      (GPFDAT&(1<< 0)) == 0 )              { returnvalue= 11;goto out;}        else if( (GPFDAT&(1<< 2)) == 0 )              { returnvalue= 8 ;goto out;}        else if( (GPGDAT&(1<< 3)) == 0 )              { returnvalue= 5 ;goto out;}        else if( (GPGDAT&(1<<11)) == 0 )              { returnvalue= 2 ;goto out;}                                                                                                                                                       //扫描键盘第1列 K10、K7、K4、K1        GPGDAT = GPGDAT & (~((1<<6)|(1<<2))) | (1<<6) | (1<<2) ;                      //GPG6 output 1;GPG2 output 1        GPEDAT = GPEDAT & (~((1<<13)|(1<<11))) | (1<<13) | (0<<11) ;          //GPE13 output 1;GPE11 output 0        if(      (GPFDAT&(1<< 0)) == 0 )              { returnvalue= 10;goto out;}         else if( (GPFDAT&(1<< 2)) == 0 )              { returnvalue= 7; goto out;}         else if( (GPGDAT&(1<< 3)) == 0 )              { returnvalue= 4; goto out;}        else if( (GPGDAT&(1<<11)) == 0 )              { returnvalue= 1; goto out;}                                                                                                                                                       //扫描键盘第3列 K12、K9、K6、K3        GPGDAT = GPGDAT & (~((1<<6)|(1<<2))) | (1<<6) | (1<<2) ;                      //GPG6 output 1;GPG2 output 1        GPEDAT = GPEDAT & (~((1<<13)|(1<<11))) | (0<<13) | (1<<11) ;          //GPE13 output 0;GPE11 output 1        if(      (GPFDAT&(1<< 0)) == 0 )               returnvalue= 12 ;        else if( (GPFDAT&(1<< 2)) == 0 )               returnvalue= 9 ;        else if( (GPGDAT&(1<< 3)) == 0 )               returnvalue= 6 ;        else if( (GPGDAT&(1<<11)) == 0 )               returnvalue= 3 ;        else returnvalue= 0xff ;out:        //重新初始化IO口        GPGCON = GPGCON & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)) ;            //GPG6,2 set output        GPGDAT = GPGDAT & (~((1<<6)|(1<<2)));         //GPG6,2 output 0                                                                                                                                                      GPECON = GPECON & (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22));           //GPE13,11 set output        GPEDAT = GPEDAT & (~((1<<13)|(1<<11)));               //GPE13,11 output 0                                                                                                                                                       GPGCON = GPGCON & (~((3<<22)|(3<<6))) | ((2<<22)|(2<<6)) ;            //GPG11,3 set EINT        GPFCON = GPFCON & (~((3<<4)|(3<<0))) | ((2<<4)|(2<<0)) ;              //GPF2,0 set EINTspin_lock_irq (&my_lock);//解锁	return returnvalue;}*/static struct key_info {	int irq_no;	unsigned int gpio_port;	unsigned int gpio_port_kscan;	int key_no;} key_info_tab[16] = {	/*键盘第1列 k10 k7 k4 k1*/	{ IRQ_EINT19, GPIO_G11, GPIO_E11, 1 },	{ IRQ_EINT11, GPIO_G3, GPIO_E11, 4 },	{ IRQ_EINT2, GPIO_F2, GPIO_E11, 7 },	{ IRQ_EINT0, GPIO_F0, GPIO_E11, 10 },		/*键盘第2列 k11 k8 k5 k2*/	{ IRQ_EINT19, GPIO_G11, GPIO_G6, 2 },	{ IRQ_EINT11, GPIO_G3, GPIO_G6, 5 },	{ IRQ_EINT2, GPIO_F2, GPIO_G6, 8 },	{ IRQ_EINT0, GPIO_F0, GPIO_G6, 11 },		/*键盘第3列 k12 k9 k5 k3*/	{ IRQ_EINT19, GPIO_G11, GPIO_E13, 3 },	{ IRQ_EINT11, GPIO_G3, GPIO_E13, 6 },	{ IRQ_EINT2, GPIO_F2, GPIO_E13, 9 },	{ IRQ_EINT0, GPIO_F0, GPIO_E13, 12 },		/*键盘第4列 k16 k15 k14 k13*/	{ IRQ_EINT19, GPIO_G11, GPIO_G2, 13 },	{ IRQ_EINT11, GPIO_G3, GPIO_G2, 14 },	{ IRQ_EINT2, GPIO_F2, GPIO_G2, 15 },	{ IRQ_EINT0, GPIO_F0, GPIO_G2, 16 },};static int eint[4] = {IRQ_EINT19, IRQ_EINT11, IRQ_EINT2, IRQ_EINT0};static unsigned int ioport[4] = {GPIO_G11, GPIO_G3, GPIO_F2, GPIO_F0};static unsigned int kscan[4] = {GPIO_E11, GPIO_G6, GPIO_E13, GPIO_G2};static int ready = 0;static int key_value = 0;/*初始化按键的等待队列*/static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);/* 初始化kscan口为输出0 */static void buttons_io_port_init(void){	int i;	for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) {		set_gpio_ctrl(kscan[i] | GPIO_PULLUP_DIS | GPIO_MODE_OUT);		write_gpio_bit(kscan[i], 0);	}}/* 设置单个kscan口为输出0 */static void buttons_kscan_reset(int column){	int i;	for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) {		if(i == column)			write_gpio_bit(kscan[i], 0);		else			write_gpio_bit(kscan[i], 1);	}}/* 设置GPIO口为输入状态 */static void buttons_port_reset(void){	int i;	for(i=0; i < sizeof ioport / sizeof ioport[1]; i++) {		set_gpio_ctrl(ioport[i] | GPIO_PULLUP_DIS | GPIO_MODE_IN);	}}/* 重新设置中断 */static void buttons_int_reset(void){	int i;	for(i=0; i < sizeof eint / sizeof eint[1]; i++) {		set_external_irq(eint[i], EXT_FALLING_EDGE, GPIO_PULLUP_DIS);	}}static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg){	struct key_info *k;	int i, j;	int found = 0;	int up = -1;	int column = 0;	int row = 0;		buttons_port_reset();    /* 设置GPIO为输入状态 */		udelay(10000); /*延时10000us*/	/* 键盘扫描 */	for ( j = 0; j < sizeof kscan / sizeof kscan[1]; j++) {		buttons_kscan_reset(j);		column = j;		for ( i = 0; i < sizeof eint / sizeof eint[1]; i++) {			if(eint[i] == irq) {				row = i;				up = read_gpio_bit(ioport[i]);				break;			}		}		if(up == 0) {			found = 1;			break;		}	}	udelay(10000);                              /* 延时去抖 */		if (found) {		k = key_info_tab + column * 4 + row;		if (up) {			key_value = k->key_no + 0x80;//		} else {			key_value = k->key_no;		}	}		ready = 1;	wake_up_interruptible(&buttons_wait);	buttons_io_port_init();     /* 重新设置GPIO为输出 */	buttons_int_reset();        /* 重新设置中断 */}static int request_irqs(void){	int i;		for (i = 0; i < sizeof eint / sizeof eint[1]; i++) {		set_external_irq(eint[i], EXT_FALLING_EDGE, GPIO_PULLUP_DIS);		 //设置与外部中断号相对应的GPIO端口,下降沿触发,上拉寄存器是禁止的		if (request_irq(eint[i], &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq)) {			return -1;		}	/*请求中断,所有的按键都使用同一个中断处理程序。中断处理程序根据中断号确定按下的是哪一个按键。*/	}	return 0;}static void free_irqs(void){	int i;		for (i = 0; i < sizeof eint / sizeof eint[1]; i++)		free_irq(eint[i], buttons_irq);}static int matrix4_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos){	static int key;	int flags;	int repeat;		if (!ready)		return -EAGAIN;			if (count != sizeof key_value)		return -EINVAL;			save_flags(flags); //没有必要		if (key != key_value) {		key = key_value;		repeat = 0;	} else {		repeat = 1;	}		restore_flags(flags);		/*if (repeat) {		return -EAGAIN;	}*/		copy_to_user(buffer, &key, sizeof key);	ready = 0;		return sizeof key_value;}static unsigned int matrix4_buttons_select(struct file *file, struct poll_table_struct *wait){	if (ready)		return 1;			poll_wait(file, &buttons_wait, wait); 	//通过调用函数 poll_wait,增加buttons_wait等待队列到poll_table 结构。	//poll 方法是 3 个系统调用的后端: poll, epoll, 和 select.(from ldd)	// 用作查询对一个或多个文件描述符的		return 0;}static int matrix4_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	switch(cmd) {	default:		return -EINVAL;	}}static struct file_operations matrix4_buttons_fops = {	owner: THIS_MODULE,	ioctl: matrix4_buttons_ioctl,	poll:  matrix4_buttons_select,	read:  matrix4_buttons_read,};static devfs_handle_t devfs_handle;static int __init matrix4_buttons_init(void){	int ret;	ready = 0;	ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &matrix4_buttons_fops);		if (ret < 0) {		printk(DEVICE_NAME " can't register major number\n");		return ret;	}	buttons_io_port_init();		ret = request_irqs();	if (ret) {		unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);		printk(DEVICE_NAME " can't request irqs\n");		return ret;	}		devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT, BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &matrix4_buttons_fops, NULL);		return 0;}static void __exit matrix4_buttons_exit(void){	devfs_unregister(devfs_handle);	free_irqs();	unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);}module_init(matrix4_buttons_init);module_exit(matrix4_buttons_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -