(驱动)(中断)(定时器)中断结合定时器完成按键消抖的驱动程序

       用定时器结合中断,完成按键消抖的功能,有按键按下即中断发生,修改定时时间并激活定时器。定时器通过msecs_to_jiffies(20)定时20mS,启动定时器处理函数,检测按键,如果按键还处于低电平状态,则将改变状态(也即亮变成灭,灭变成亮),并打印"hello keyboard"。

        将.ko文件开发板下到开发板上,输入命令:echo > led  即可进行按键操作。



#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include
#include 

static volatile unsigned int *GPJ2CON;
static volatile unsigned int *GPJ2DAT;
static volatile unsigned int *GPH2CON;
static volatile unsigned int *GPH2DAT;

struct timer_list time;
static int major,flag = 0;

irqreturn_t key_interr(int irqno,void *dev)
{

if( !( (*GPH2DAT) & 1 )) //有按键(K1)按下,修改定时时间,重新激活定时器,定时20ms	
	mod_timer(&time,jiffies + msecs_to_jiffies(20));	//修改定时时间
	
	return IRQ_HANDLED;
		
}

/*定时器处理函数*/
static void timer_fun(unsigned long arg)
{
	if( !( (*GPH2DAT) & 1 ))//如果按键还是低电平(继续按下)执行以下程序
	{
		printk("hello keyboard\n");
	
		flag = ~flag;
		if(0 == flag)
			*GPJ2DAT &= 0xf0;//点亮LED
		else
			*GPJ2DAT |= 0x0f;//熄灭LED
	}
}

static int led_open(struct inode *pi, struct file *pf)
{
	GPJ2CON = ioremap(0xe0200280,8);//物理地址映射成核心虚地址
	GPJ2DAT = GPJ2CON + 1;
	
	GPH2CON = ioremap(0xe0200c40,8);
	GPH2DAT = GPH2CON+1;

	*GPJ2CON &= 0xffff0000;
	*GPJ2CON |= 0x00001111;	//设置为输出
	*GPJ2DAT |= 0x0f;	//熄灭所有LED
	
	*GPH2CON |= 0x0000000f;	//K1键设置为外部中断
	
	init_timer(&time);//初始化定时器
	time.function = &timer_fun;
	time.expires = jiffies + msecs_to_jiffies(20);
	add_timer(&time);//添加,启动定时器
	
	request_irq(IRQ_EINT(16),key_interr,IRQF_TRIGGER_FALLING,"key1",NULL);//中断请求函数
	
	return 0;
}

static ssize_t led_write(struct file *pf, const char __user *pbuf, size_t len, loff_t *ppos)
{
	
	return 0;
}

ssize_t led_read (struct file *pf, char __user *pbuf, size_t count, loff_t *off)
{
	
	return 0;
}

static int led_release(struct inode *pi, struct file *pf)
{
	del_timer(&time);//删除定时器
	printk(" test release.\n");
	return 0;
}

static struct file_operations t_fops=
{
	.owner		= THIS_MODULE,
	.open 		= led_open,
	.release	= led_release,
	.write 		= led_write,
	.read 		= led_read,
};

static __init int led_init(void)
{
	major = register_chrdev(0,"LED",&t_fops);
	printk("major = %d\n",major);
	return 0;
}

static __exit void led_exit(void)
{
	iounmap(GPJ2CON);
	iounmap(GPH2CON);
	unregister_chrdev(major,"LED");
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huang Dezhi");
MODULE_DESCRIPTION("This is the interrupt");


你可能感兴趣的:(ARM学习笔记,ARM-LINUX驱动学习)