哪位大哥做过旋转编码开关程序帮忙看一下!

发布于 2022-09-29 23:03:38 字数 8000 浏览 27 评论 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种状态一起比较的
我按上面处理方法能正常输出,也不会出现误码,只是在转换方向时,不能立即变向,而是在两次中断后在换过来,
当我只取其中两位分别比较时,能立即转换方向,但会出现误码(即出现反向的输出值)
请高手帮忙指点一下,或提供一下这方面的经验,在此感激不尽!谢谢!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

提笔落墨 2022-10-06 23:03:38

PIC的芯片好多都具有自动解这种正交编码的能力,
如果转速比较快的话,是否可以考虑不用系统cpu做这件事,外扩一个微处理器
或者加一个Index校正(PIC就是这样做的)。

奢欲 2022-10-06 23:03:38

谢谢!
不过,我现在不大可能另增加PIC,我再想想办法!

小红帽 2022-10-06 23:03:38

这位大哥,我也刚遇到你这样的问题!!你解决了没有?

鹿港小镇 2022-10-06 23:03:38

这种叫正交编码器(QEI),用STM32的TIMER做(它有QEI模式)或者用FPGA自己做合适。软件中断计数这玩法实在不怎么靠谱的。
我们公司生成光栅尺的,也是这种接口,有同事为省成本做过这种测试,结果当然是走不通,只要你手一抖动,速度就会快得中断忙不过来。
除非你有机构带着保证不会速度不稳,要求的速度也不高,否则不太可能用软件中断来做。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文