- 论坛徽章:
- 0
|
哪位大哥做过旋转编码开关程序帮忙看一下!
我最近在做旋转编码开关驱动程序,碰到一点问题,请高手帮忙看一下:
是基于2410 linux2.6内核的
旋转编码开关运动周期的时序为
顺时针运动: A B 逆时针运动: A B
1 1 1 1
0 1 1 0
0 0 0 0
1 0 0 1
我把当前的A,B输出值保存起来,与下一个A,B输出值做比较,得出运动方向(如果A,B输出11后输出01,则为顺时针;如果输出11后马上输出10,则为逆时针),
我采用的是双边缘中断方式,其中A接到INT16(GPIOG ,接到INT8(GPIOG0),以下是我的驱动程序中的中断处理函数
static unsigned int inc[] = {0,0,0,0};
static unsigned int dec[] = {0,0,0,0};
//static int a=0;
unsigned int right=0, left=0,irq_num=0;
static irqreturn_t buttons2_irq(int irq, void *dev_id, struct pt_regs *reg)
{
unsigned int gpg_con2,gpg_dat2,gpg_up2;
unsigned long flags;
disable_irq(irq);
irq_num = irq_num + 1;
//local_irq_save(flags);
unsigned int k1 = 0,k2 = 0;
gpg_con2=readl(gpbase+0x60); //取出G端口控制字寄存器值
gpg_dat2=readl(gpbase+0x64); // 取出G端口数据寄存器值
gpg_up2=readl(gpbase+0x6 ; // 取出G端口上拉寄存器值
writel(gpg_con2 & 0xfffcfffc,gpbase+0x60);//G端口中G0、G8管脚设为输入模式
writel(gpg_up2 | 0x0101,gpbase+0x6 ;
k1 = s3c2410_gpio_getpin(S3C2410_GPG ;
k2 = s3c2410_gpio_getpin(S3C2410_GPG0);
writel(gpg_con2 & 0xfffefffe,gpbase+0x60);//G端口中G0、G8管脚设为中断模式
set_irq_type(INC_IRQ,IRQT_BOTHEDGE);
set_irq_type(DEC_IRQ,IRQT_BOTHEDGE);
//printk("%x,%x\n",k1,k2);
inc[3] = k1;
dec[3] = k2;
if((inc[0]==0x100) && (dec[0]==1)){ //1
if((inc[1]==0) && (dec[1]==1)){
if((inc[2]==0) && (dec[2]==0)){
if((inc[3]==0x100) && (dec[3]==0)){
right = 1;
left = 0;
}
}
}
}
if((inc[0]==0x100) && (dec[0]==1)){ //2
if((inc[1]==0x100) && (dec[1]==0)){
if((inc[2]==0) && (dec[2]==0)){
if((inc[3]==0) && (dec[3]==1)){
right = 0;
left = 1;
}
}
}
}
if((inc[0]==0) && (dec[0]==1)){ //3
if((inc[1]==0) && (dec[1]==0)){
if((inc[2]==0x100) && (dec[2]==0)){
if((inc[3]==0x100) && (dec[3]==1)){
right = 1;
left = 0;
}
}
}
}
if((inc[0]==0x100) && (dec[0]==0)){ //4
if((inc[1]==0) && (dec[1]==0)){
if((inc[2]==0) && (dec[2]==1)){
if((inc[3]==0x100) && (dec[3]==1)){
right = 0;
left = 1;
}
}
}
}
if((inc[0]==0) && (dec[0]==0)){ //5
if((inc[1]==0x100) && (dec[1]==0)){
if((inc[2]==0x100) && (dec[2]==1)){
if((inc[3]==0) && (dec[3]==1)){
right = 1;
left = 0;
}
}
}
}
if((inc[0]==0) && (dec[0]==0)){ //6
if((inc[1]==0) && (dec[1]==1)){
if((inc[2]==0x100) && (dec[2]==1)){
if((inc[3]==0x100) && (dec[3]==0)){
right = 0;
left = 1;
}
}
}
}
if((inc[0]==0x100) && (dec[0]==0)){ //7
if((inc[1]==0x100) && (dec[1]==1)){
if((inc[2]==0) && (dec[2]==1)){
if((inc[3]==0) && (dec[3]==0)){
right = 1;
left = 0;
}
}
}
}
if((inc[0]==0) && (dec[0]==1)){ //8
if((inc[1]==0x100) && (dec[1]==1)){
if((inc[2]==0x100) && (dec[2]==0)){
if((inc[3]==0) && (dec[3]==0)){
right = 0;
left = 1;
}
}
}
}
inc[0] = inc[1];
dec[0] = dec[1];
inc[1] = inc[2];
dec[1] = dec[2];
inc[2] = inc[3];
dec[2] = dec[3];
if(irq_num==1){
if(right==1)
key_value = 0x14;//int=20,正向递增
else if(left==1)
key_value = 0x15;//int=21,逆向递减
ready = 1;
wake_up_interruptible(&buttons_wait);
}
else
irq_num = 0;
enable_irq(irq);
//local_irq_restore(flags);
return IRQ_HANDLED;
}
我是对4种状态一起比较的
我按上面处理方法能正常输出,也不会出现误码,只是在转换方向时,不能立即变向,而是在两次中断后在换过来,
当我只取其中两位分别比较时,能立即转换方向,但会出现误码(即出现反向的输出值)
请高手帮忙指点一下,或提供一下这方面的经验,在此感激不尽!谢谢! |
|