今天小心奕奕的把代码拷出来,是个按键驱动,大家帮忙看一下
本帖最后由 0vk0 于 2011-03-04 19:50 编辑是个按键驱动,大家帮忙看一下,现在按键抬起可以检测到,但再按别的
我测试时老是出现:
当换一个按键时,会出现前一个按键,比如我按1时,按下会打印1,抬起会打印1,当我换按2时,第一遍按下会打印1,抬起会打印2,再第二遍的时候就不会了
当我换按5时,第一遍按下会打印2,抬起会打印5,再第二遍的时候也不会了,请帮帮忙看下程序,谢谢了,第二个是应该层的测试程序#include <asm/gpio.h>
#include <asm/jzsoc.h>
……
#define DEVICE_NAME "keypad"
#define MAX_KEY_COUNT32
#define HC164_CP 89 //kb2
#define HC164_DS 88 //kb1
#define INT_KEY1 93 //kb3
#define INT_KEY2 91 //kb4
#define KEY1_IRQ (IRQ_GPIO_0 + INT_KEY1)
#define KEY2_IRQ (IRQ_GPIO_0 + INT_KEY2)
typedef struct
{
unsigned long jiffy;
unsigned char buf;
unsigned int head,tail;
}KEY_BUFFER;
static KEY_BUFFER g_keyBuffer;
static spinlock_t buffer_lock;
static int Keypad_major = 255;
int a=200,b=201;
/*
*/
static unsigned long GetTickCount(void)
{
struct timeval currTick;
unsigned long ulRet;
do_gettimeofday(&currTick);
ulRet = currTick.tv_sec;
ulRet *= 1000;
ulRet += (currTick.tv_usec + 500) / 1000;
return ulRet;
}
/*
*/
static void init_keybuffer(void)
{
int i;
spin_lock_irq(&buffer_lock);
g_keyBuffer.head = 0;
g_keyBuffer.tail = 0;
for(i = 0; i < MAX_KEY_COUNT; i++)
{
g_keyBuffer.buf = 0;
g_keyBuffer.jiffy = 0;
}
spin_unlock_irq(&buffer_lock);
}
/*
*/
static void remove_timeoutkey(void)
{
unsigned long ulTick;
spin_lock_irq(&buffer_lock);
while(g_keyBuffer.head != g_keyBuffer.tail)
{
ulTick = GetTickCount() - g_keyBuffer.jiffy;
if (ulTick< 5000)
break;
g_keyBuffer.buf = 0;
g_keyBuffer.jiffy = 0;
g_keyBuffer.head ++;
g_keyBuffer.head &= (MAX_KEY_COUNT -1);
}
spin_unlock_irq(&buffer_lock);
}
/*
*/
void _74HC164Send(unsigned char d)
{
int j;
for(j=0;j<8;j++)
{
if (d&1)
__gpio_set_pin(HC164_DS);
else
__gpio_clear_pin(HC164_DS);
mdelay(1);
__gpio_set_pin(HC164_CP);
mdelay(1);
__gpio_clear_pin(HC164_CP);
d >>= 1;
}
}
/*
*/
static void init_gpio(void)
{
__gpio_as_input(INT_KEY1);
__gpio_as_input(INT_KEY2);
__gpio_as_output(HC164_CP);
__gpio_as_output(HC164_DS);
__gpio_clear_pin(HC164_CP);
__gpio_clear_pin(HC164_DS);
_74HC164Send(0);
}
/*
*/
static __inline void enable_irqs(void)
{
unsigned long flags;
spin_lock_irqsave(buffer_lock, flags);
__gpio_unmask_irq(INT_KEY1);
__gpio_unmask_irq(INT_KEY2);
spin_unlock_irqrestore(buffer_lock, flags);
}
/*
*/
static __inline void disable_irqs(void)
{
unsigned long flags;
spin_lock_irqsave(buffer_lock, flags);
__gpio_mask_irq(INT_KEY1);
__gpio_mask_irq(INT_KEY2);
spin_unlock_irqrestore(buffer_lock, flags);
}
/*
*/
static unsigned char num = 0;
static __inline unsigned char button_scan(int irq)
{
unsigned char ret=0xff;
unsigned char i;
if(!(__gpio_get_pin(INT_KEY1)))
{
for(i=1;i<9;i++)
{
printk("i=%d\n",i);
__gpio_set_pin(HC164_DS);
mdelay(1);
__gpio_set_pin(HC164_CP);
mdelay(1);
__gpio_clear_pin(HC164_CP);
if(__gpio_get_pin(INT_KEY1))
{
num=i; //此处改动过
return i;
}
}
}
else
{
if(!(__gpio_get_pin(INT_KEY2)))
{
for(i=1;i<9;i++)
{
printk("key2 i=%d\n",i);
__gpio_set_pin(HC164_DS);
mdelay(1);
__gpio_set_pin(HC164_CP);
mdelay(1);
__gpio_clear_pin(HC164_CP);
if(__gpio_get_pin(INT_KEY2))
{
num=i+8; //此处改动
return i;
}
}
}
}
return ret ;
}
/*
*
*/
static irqreturn_t button_down_irq(int irq, void *dev_id)
{
unsigned char ucKey;
disable_irqs();
udelay(1000);
ucKey = button_scan(irq);
if ((ucKey >= 1) && (ucKey <= 16))
{
if (((g_keyBuffer.head + 1) & (MAX_KEY_COUNT - 1)) != g_keyBuffer.tail)
{
spin_lock_irq(&buffer_lock);
g_keyBuffer.buf = ucKey;
g_keyBuffer.jiffy = GetTickCount();
g_keyBuffer.tail ++;
g_keyBuffer.tail &= (MAX_KEY_COUNT - 1);
spin_unlock_irq(&buffer_lock);
}
}
_74HC164Send(0);
__gpio_ack_irq(INT_KEY1); // clear status
__gpio_ack_irq(INT_KEY2); // clear status
enable_irqs();
return IRQ_HANDLED;
}
static irqreturn_t button_rise_irq(int irq, void *dev_id)
{
unsigned char ucKey;
disable_irqs();
udelay(1000);
ucKey = num;
// *****************************
buttonup_scan();
if ((ucKey >= 1) && (ucKey <= 16))
{
if (((g_keyBuffer.head + 1) & (MAX_KEY_COUNT - 1)) != g_keyBuffer.tail)
{
spin_lock_irq(&buffer_lock);
g_keyBuffer.buf = ucKey;
g_keyBuffer.jiffy = GetTickCount();
g_keyBuffer.tail ++;
g_keyBuffer.tail &= (MAX_KEY_COUNT - 1);
spin_unlock_irq(&buffer_lock);
}
}
_74HC164Send(0);
__gpio_ack_irq(INT_KEY1); // clear status
__gpio_ack_irq(INT_KEY2); // clear status
enable_irqs();
return IRQ_HANDLED;
}
/*
*
*/
static int request_irqs(void)
{
__gpio_as_irq_fall_edge(INT_KEY1); //下降沿发生中断
__gpio_as_irq_fall_edge(INT_KEY2);
__gpio_as_irq_rise_edge(INT_KEY1); //上升沿发生中断
__gpio_as_irq_rise_edge(INT_KEY2);
if(request_irq(KEY1_IRQ, button_rise_irq, IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &a)){
printk("Could not allocate key1 IRQ:%d\n",KEY1_IRQ);
return -EINVAL;
}
if(request_irq(KEY2_IRQ, button_rise_irq,IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &a)){
free_irq(KEY1_IRQ, &a);
printk("Could not allocate key2 IRQ:%d\n",KEY2_IRQ);
return -EINVAL;
}
if(request_irq(KEY1_IRQ, button_down_irq,IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &b)){
printk("Could not allocate key1 IRQ:%d\n",KEY1_IRQ);
return -EINVAL;
}
if(request_irq(KEY2_IRQ, button_down_irq,IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &b)){
free_irq(KEY1_IRQ, &b);
printk("Could not allocate key2 IRQ:%d\n",KEY2_IRQ);
return -EINVAL;
}
__gpio_ack_irq(INT_KEY1); // clear status
__gpio_ack_irq(INT_KEY2); // clear status
return 0;
}
/*
*
*/
static __inline void free_irqs(void)
{
free_irq(KEY1_IRQ, &a);
free_irq(KEY1_IRQ, &b);
free_irq(KEY2_IRQ, &a);
free_irq(KEY2_IRQ, &b);
}
/*
*
*/
static int keypad_open(struct inode *inode,struct file *filp)
{
int ret = nonseekable_open(inode, filp);
if (ret >= 0)
{
printk("keypad opened ret>0.\n");
init_keybuffer();
enable_irqs();
}
printk("keypad opened.\n");
return ret;
}
/*
*
*/
static int keypad_release(struct inode *inode,struct file *filp)
{
disable_irqs();
printk("keypad release.\n");
return 0;
}
/*
*
*/
static ssize_t keypad_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
ssize_t ret = 0;
remove_timeoutkey();
spin_lock_irq(&buffer_lock);
while((g_keyBuffer.head != g_keyBuffer.tail) && (((size_t)ret) < count) )
{
buffer = (char)(g_keyBuffer.buf);
g_keyBuffer.buf = 0;
g_keyBuffer.jiffy = 0;
g_keyBuffer.head ++;
g_keyBuffer.head &= (MAX_KEY_COUNT - 1);
ret ++;
}
spin_unlock_irq(&buffer_lock);
return ret;
}
/*
*
*/
static int keypad_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
init_keybuffer();
return 1;
}
/*
*/
static void led_setup_cdev(struct cdev *dev,int minor,struct file_operations *fops)
{
int err;
int devno=MKDEV(Keypad_major,minor);
cdev_init(dev,fops);
dev->owner=THIS_MODULE;
dev->ops=fops;
err=cdev_add(dev,devno,1);
if(err)
printk(KERN_INFO"Error %d adding button %d\n",err,minor);
}
/*
*/
static struct file_operations keypad_fops =
{
.owner = THIS_MODULE,
.ioctl = keypad_ioctl,
.open = keypad_open,
.read = keypad_read,
.release = keypad_release,
};
static struct cdev SimpleDevs;
/*
*
*/
static intKeyPad_Init(void)
{
int ret;
int result;
dev_t dev;
dev=MKDEV(Keypad_major,0);
if(Keypad_major)
result=register_chrdev_region(dev,1,DEVICE_NAME);
else
{
result=alloc_chrdev_region(&dev,0,1,DEVICE_NAME);
Keypad_major=MAJOR(dev);
}
if(result<0)
{
printk(KERN_WARNING"Keypad:unable to get major %d\n",Keypad_major);
return result;
}
if(Keypad_major==0)
Keypad_major=result;
led_setup_cdev(&SimpleDevs,0,&keypad_fops);
init_gpio();
ret = request_irqs();
if (ret < 0)
{
cdev_del(&SimpleDevs);
unregister_chrdev_region(MKDEV(Keypad_major,0),1);
return ret;
}
printk(KERN_INFO"keypad register ok!!!!!!!!!!\n");
return 0;
}
/*
*
*/
static void __exit KeyPad_Exit(void)
{
disable_irqs();
free_irqs();
cdev_del(&SimpleDevs);
unregister_chrdev_region(MKDEV(Keypad_major,0),1);
printk("button device uninstalled\n");
}
module_init(KeyPad_Init);
module_exit(KeyPad_Exit);
MODULE_AUTHOR("zhyh");
MODULE_DESCRIPTION("keypad driver");
MODULE_LICENSE("GPL");
你这个很难说出什么问题,程序本身估计没什么问题,与处理逻辑可能关系很大 你这个很难说出什么问题,程序本身估计没什么问题,与处理逻辑可能关系很大
dreamice 发表于 2011-03-05 11:35 http://linux.chinaunix.net/bbs/images/common/back.gifif(request_irq(KEY1_IRQ, button_rise_irq, IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &a)){
printk("Could not allocate key1 IRQ:%d\n",KEY1_IRQ);
return -EINVAL;
}
这里是否正确 ,我这里IRQF_DISABLED | IRQF_SHARED换成IRQF_TRIGGER_FALLING | IRQF_DISABLED |和IRQF_TRIGGER_FALLING |IRQF_DISABLED ,就会出现insmod: cannot insert 'key.ko': invalid parameter ,我知道是dev_id这里错误,但是我应该怎么改,请大虾赐教 首先
struct button_irq_desc {
int irq;
int gpio;
};
static struct button_irq_desc button_irqs [] = {
{IRQ_EINTx, GPx0(x)}, /* K1 */
{xxxxxxxxxxxxxxxxx} , /*K2*/
...
};
然后把你的申请写成个循环
其次,参数写成IRQF_SHARED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
处理所谓按下抬起,在一个中断处理里做就可以了。
最后,你去看看gpio_keys.c
内核是最好的老师,抄吧。不是非得写的跟内核不一样才能彰显代码的个性……
页:
[1]