打印

编码器的问题,求助!!!

[复制链接]
楼主: DownCloud
手机看帖
扫描二维码
随时随地手机跟帖
41
yehua108| | 2011-8-19 16:06 | 只看该作者 回帖奖励 |倒序浏览
:lol:lol:lol

使用特权

评论回复
42
Cortex-M0| | 2011-8-19 16:22 | 只看该作者
42# dengm

dengm大虾的抗干扰中断计数程序编的很巧妙。

把这个老土的烂51用到极致,赞一个~~~

现在芯片的功能都增强了不少,已很少人这样用了。

使用特权

评论回复
43
dengm| | 2011-8-19 16:28 | 只看该作者
软件:
用p3.2 门控, Timer0 , 上/下边缘都中断
用p3.3 门控, Timer1 , 上/下边缘都中断
就能真正完成任务!!!

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Cortex-M0 + 1
44
Cortex-M0| | 2011-8-19 16:42 | 只看该作者
dengm老师正解!

从双重计数法,在计数频率不是很高时,能可靠完成4线分~~~

使用特权

评论回复
45
dengm| | 2011-8-19 17:06 | 只看该作者
没有给出速度范围, 就不能给你建议最佳方案了

使用特权

评论回复
46
A2000wps| | 2011-8-19 18:15 | 只看该作者
有空看看

使用特权

评论回复
47
eydj2008| | 2011-8-20 12:44 | 只看该作者
19# DownCloud

你不会是想要现成的吧?

真的只有几行(8行左右面)  我以前做过一个这样的项目,这电脑上没有,想了很久,结果发现 几行代码 弄死大脑。(不加滤波的情况)

使用特权

评论回复
48
DownCloud|  楼主 | 2011-8-20 14:50 | 只看该作者
49# eydj2008
没有现成的你也提供一下你大脑是怎么想的,敲代码我还是比较在行的,嘿嘿。

使用特权

评论回复
49
DownCloud|  楼主 | 2011-8-20 15:05 | 只看该作者
42# dengm
dengm 的51汇编水平不得不让人叹为观止,
浏览了你以前的帖子,
程序中追求完美的艺术。
我刚学51汇编的时候也写过一个双字节除以1000的汇编程序。也很快。
很久没用汇编写什么特殊的程序了,持起不易。数学计算大都是用C语言随便敲几下就 完事。(程序执行的时间看起来也觉得恶心,不过幸好,一般都会在我留的时间内)
路还很漫长,而我已经离汇编越来越远了。

使用特权

评论回复
50
gpsvf| | 2011-8-20 20:16 | 只看该作者
呵呵,路过

使用特权

评论回复
51
tf_0991| | 2011-8-21 12:19 | 只看该作者
感觉楼主的硬件是不是出问题了,一般编码器有些轻微的振动不会一直产生计数脉冲的。楼主可以检查一下上拉电阻是否合适。另外一般的这种编码器计数脉冲都要做一定的数字滤波,滤除这些误计数脉冲,可以用触发器来硬件实现,或者用软件滤波。

使用特权

评论回复
52
fly1974| | 2011-8-22 10:09 | 只看该作者
下面的算法应该可以,不过前提是那些干扰脉冲不是非常窄,单片机识别没问题

#pragma interrupt_handler TIMER3_OVF_ISR: 30                    //1
void TIMER3_OVF_ISR(void)                                       //1
{                                                              //1
    TCNT3=0xfc41;                                               //1 125uS
    if(!Comparing) {                                            //1
                           PulAPol=PINE; PulLastState=PulAPol; Comparing++;   //1
                                                   PulAPol&=0x40; PulLastState&=0xc0; PulAPol>>=6;    //1
                                           }                                                    //1
        if(Comparing)                                                         //1
         {                                                                    //1
            PulBPol=PINE;                                                     //1
      PulState=PulBPol;                                                 //1
      PulState&=0xc0;                                                   //1
                  PulBPol&=0x80;                                                    //1
                  PulBPol>>=7;                                                      //1
                  if(PulState!=PulLastState)
                          {
                                  if(PulBPol==PulAPol)
                                          {
                                                  RunRight=1; BMQCounterTotal--;
                                          }
                            else
                                    {
                                            RunRight=0; BMQCounterTotal++;
                                          }
                            Comparing=0;  
                          }  //1
         }                                                                    //1
    if(!Comparing) {                                                    //1
                           PulAPol=PulState; PulLastState=PulAPol; Comparing++; //1
                                                   PulAPol&=0x40; PulLastState&=0xc0; PulAPol>>=6;      //1
                                           }                                                      //1
}

使用特权

评论回复
53
fly1974| | 2011-8-22 10:16 | 只看该作者
因为没注释,大概解释一下: A和B只要有一个变化就计数,A=B右转,总数+1,A!=B左转,总数-1

使用特权

评论回复
54
fly1974| | 2011-8-22 18:37 | 只看该作者
解释有点小问题,代码没有,代码是从产品代码中剪出来的,主要是为了克服多次来回走编码器计数重复多1或少1的问题研究出来的,对楼主的问题应该有帮助。

使用特权

评论回复
55
dengm| | 2011-8-23 10:26 | 只看该作者
本帖最后由 dengm 于 2011-8-23 10:28 编辑

软件:    用p3.2 门控, Timer0 , 上/下边缘都中断; P3.3 下边缘中断

$MOD51
   c_Delay equ 10 ; 延时采样
   Status data 20h
   f_DIR BIT Status.2
   f_ST0 BIT Status.0 ;00 01 02/03
   F_ST1 BIT Status.1
   A_BAK  DATA 30H
   CntL   data 31h
   CntH   data 32h

   ;P3.3  "0"      "0"
   ;          ==>>       INC Cnt   Setb f_Dir     
   ;P3.2  "0"      "1"  

   ;P3.3  "0"      "0"
   ;          ==>>       DEC Cnt   clr f_Dir
   ;P3.2  "1"      "0"  
   
   ORG 0000H
     NOP
     AJMP START

   ORG 0003H ; INT 0  P3.2 =0
     MOV TL0, #(256-c_Delay)
     SETB TR0     
     SJMP L_UP_DN
     
   ORG 000BH ; TIMER 0 P3.2=1
     CLR TR0
     SJMP L_UP_DN

   ORG 0013H ; Int 1 P3.3 = 0
     SJMP L_UP_DN
   
   ORG 0050H
L_UP_DN:
      MOV A_BAK, A
      MOV A, P3
      ANL A, #1100B
      JNB f_ST1, L_UP_DN_0_1      
        MOV C, ACC.2
        MOV F_ST0, C
        MOV C, ACC.3
        MOV F_ST1, C
        SJMP L_UP_DN_EX         
         
L_UP_DN_0_1:
      JNB f_ST0, L_UP_DN_00
        Cjne A, #0000B, L_NO_DN
          CLR F_DIR
          CLR F_ST0  ; ==> 00                       
          MOV A, CntL
          JNZ $+4
            DEC CntH
          DEC CntL
          SJMP L_UP_DN_EX
     
L_UP_DN_00:
      JZ L_UP_DN_EX
        CJNE A, #0100B, L_NO_UP
          SETB F_DIR
          SETB F_ST0  ; ==> 01                       
          Inc CntL
          MOV A, CntL
          JNZ $+4
            INC CntH
          SJMP L_UP_DN_EX

L_NO_UP:
L_NO_DN:
        SETB f_ST1
L_UP_DN_EX:
    MOV A, A_BAK
    RETI


START:
; Configure Timer 0
;    - Mode     = 2 ; - Interrupt= ENABLED
;    - Clock Source = INTERNAL
;    - Enable Gating Control  = ENABLED
      anl   TMOD, #0F0H                  ;clear Timer 0
      orl   TMOD, #0Ah  ;
      mov   TL0,  #(256-c_Delay) ;value set by user
      mov   TH0,  #0 ;value set by user
      SETB ET0
        
      SETB IT0 ;边缘
      SETB IT1
      SETB EX0
      SETB EX1

      MOV CntL, #00
      MOV CntH, #00
      SETB F_DIR  
      SETB F_ST1
      ACALL L_UP_DN
      SETB EA
;-------------------------------
MainLoop:
     nop
     nop
     sjmp MainLoop  
     end

使用特权

评论回复
56
liudewei| | 2011-8-24 21:17 | 只看该作者
软件解决方法:
1、A、B的边沿都产生中断,中断中看AB上次状态与本次AB的转化,AB只会有00、01、11、10这四种变化,毫无疑问。00->01>11->10和00->10->11->01是正反转的关系。
2、每次跳变不是+1就是-1.
这种软件实现方法只要AB跳变的间隔时间足以完成中断响应处理流程即可。
硬件解决办法:
硬件方法1、采用现成的正交编码器即可完成正交编码的解析。很多控制类DSP内部都内嵌有正交编码器资源,设置即可使用。
硬件方法2、采用fpga可编程器件,自己采用硬件描述VHDL/verilog语言来实现。

  case status1 is
                         when s0 =>if((inaclear='1')and (inbclear='0')) then
                                   status1<=s1;
                                   --direct1<='0';
                                   --inpout1last<=inpout1;
                                   inpout0<='1';
                                   ct6<=0;
                                   elsif((inaclear='0')and (inbclear='1')) then
                                   status1<=s3;
                                   --direct1<='1';
                                   --inpout1last<=inpout1;
                                   inpout1<='1';
                                   ct6<=0;
                                   else if(int2mask(5)='0' and not((inaclear='0')and (inbclear='0'))) then
                                         codebit<='1';
                                         vecint2(5)<='1';
                                        end if;
                                   end if;
                         when s1 =>if((inaclear='1')and (inbclear='1')) then
                                   status1<=s2;
                                   --direct1<='0';
                                   --inpout1last<=inpout1;
                                   inpout0<='1';
                                   ct6<=0;
                                   elsif((inaclear='0') and (inbclear='0')) then
                                   status1<=s0;
                                   --direct1<='1';
                                   --inpout1last<=inpout1;
                                   inpout1<='1';
                                   ct6<=0;
                                   else if(int2mask(5)='0' and not((inaclear='1')and (inbclear='0'))) then
                                         codebit<='1';
                                         vecint2(5)<='1';
                                        end if;
                                   end if;
                        when s2 =>if((inaclear='0')and (inbclear='1')) then
                                   status1<=s3;
                                   --direct1<='0';
                                   --inpout1last<=inpout1;
                                   inpout0<='1';
                                   ct6<=0;
                                   elsif((inaclear='1') and (inbclear='0')) then
                                   status1<=s1;
                                   --direct1<='1';
                                   --inpout1last<=inpout1;
                                   inpout1<='1';
                                   ct6<=0;
                                   else if(int2mask(5)='0' and not((inaclear='1')and (inbclear='1'))) then
                                         codebit<='1';
                                         vecint2(5)<='1';
                                        end if;
                                   end if;
                        when s3 =>if((inaclear='0')and (inbclear='0')) then
                                   status1<=s0;
                                   --direct1<='0';
                                   --inpout1last<=inpout1;
                                   inpout0<='1';
                                   ct6<=0;
                                   elsif((inaclear='1') and (inbclear='1')) then
                                   status1<=s2;
                                   --direct1<='1';
                                   --inpout1last<=inpout1;
                                   inpout1<='1';
                                   ct6<=0;
                                   else if(int2mask(5)='0' and not((inaclear='0')and (inbclear='1'))) then
                                         codebit<='1';
                                         vecint2(5)<='1';
                                        end if;
                                   end if;
                        when OTHERS =>null;
                        end case;
给你参考。

使用特权

评论回复
57
DownCloud|  楼主 | 2011-8-25 01:10 | 只看该作者
58# liudewei
太谢谢了,这世界还是好人多一点啊!呵呵

使用特权

评论回复
58
fly1974| | 2011-8-25 12:06 | 只看该作者
58# liudewei

假定/A为A上次状态,则看/A和Bj就好了,不用看AB的四个状态

使用特权

评论回复
59
DownCloud|  楼主 | 2011-9-11 10:59 | 只看该作者
47# dengm
编码器分辨率2000p/r ,3秒左右转一圈。
我已有比较奇怪的方法,但方法是别人的,不方便公开。

使用特权

评论回复
60
zhangyong1818| | 2012-3-13 16:21 | 只看该作者
楼主有点不太地道啊,应该思想共欣赏!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则