打印

求解单片机判编码器旋转方向时的一个奇怪现象

[复制链接]
8004|40
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
catiya|  楼主 | 2011-8-17 16:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实验目的:采用单片机判定编码器旋转方向。

实验方法:外部中断法,对编码器输出的A、B两相进行判定,并由RS232串口控制查询

和输出结果。

硬件连接:编码器B相输入到外部中断0(INT0),A相输入到P3.3口。

实验原理:编码器输出的A、B两相相位相差90度,正转时A相领先B相90度,反转时B

相领先A相90度。B相下降沿触发外部中断,在外部中断服务程序中采样A相的电平,若

为高电平,则判定编码器是反向转动,若为低电平,则是正向转动。

实验现象:程序已经最简化,但是每次进入外部中断后,采样到的A相电平总是不定的,

所以判定出的编码器旋转方向总是不确定的。

程序关键部分:
......

acall uart_rx //接收串口字符

cjne a,#0cdh,error //查询串口,若收到“cd”则是判定方向指令,否则报错

acall CheckDIR
......

CheckDIR: //判定方向子程序,只做了一件事,就是打开外部中断0
   
    setb EX0 //开外部中断0

    ret
.......

EX_INT0: //外部中断服务程序

    clr EX0 //只响应一次外部中断,下次外部中断等待串口输入"cd”再次开启

    jb p3.3,setAntiCW //若p3.3为低,则改变LED1状态表示是正转

    cpl LED1
   
    reti

setAntiCW:

    cpl LED2 //若p3.3为高,则改变LED2状态表示是反转

    reti

实验手段:一开始用手转动编码器,发现判出的编码器旋转方向不定,表现为LED1和

LED2随机交替闪亮。怀疑是手转动编码器有抖动误差。后来用写了个测试程序,用另外

一块单片机口线模拟了A、B相的脉冲,用示波器观测波形正常,可模拟出要么A相超前B

相要么B相超前A相90度的稳定脉冲,但判出的旋转方向依然是不定态,无论怎样改变

A、B两相的周期,小到几us级,大到几ms级,现象相同。

判方向的单片机采用的是STC的11F01E的1T单片机,晶振22.1184M。

以上问题左思右想不得其解,望高人指点,谢谢!

相关帖子

沙发
dengm| | 2011-8-17 17:55 | 只看该作者
0  0  1  1  0  0  1  1  0  0  1  1
0  1  1  0  0  1  1  0  0  1  1  0  

中断要一直开, 用边缘方式 setb IT0

使用特权

评论回复
板凳
catiya|  楼主 | 2011-8-18 09:40 | 只看该作者
你意思是采一次采不准?我外部中断是用的边沿触发呀

使用特权

评论回复
地板
coody| | 2011-8-18 12:05 | 只看该作者
LZ用的是手动的旋转编码器么?我用的几乎都是20或24脉冲一圈的,一直用定时查询的方法,方便加数字滤波,可靠得很。

使用特权

评论回复
5
catiya|  楼主 | 2011-8-18 13:29 | 只看该作者
我的“实验手段”中描述了,一开始是采用手动旋转编码器的方法,效果不好,所以改成了用另外一块单片机口

线模拟编码器的A、B两相脉冲。效果还是一样。

coody是什么编码器,才20或24一圈,我的都是2k以上的。你的定时查询具体怎么做的,可否参考一下,也是

外部中断方式吗?

使用特权

评论回复
6
dengm| | 2011-8-18 16:51 | 只看该作者
本帖最后由 dengm 于 2011-8-18 16:53 编辑

EX_INT0:
    Push acc
    DB 0,0,0,0
    MOV A, P3
    ANL A, #00001100B
    JZ L_INT_10
       XRL A, #00000100B
       JNZ L_INT_8
          CLR  F_DIR
L_INT_8:
          POP ACC
          RETI
L_INT_10:
   SETB F_DIR
   POP ACC
   RETI

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Cortex-M0 + 1
7
DownCloud| | 2011-8-18 20:41 | 只看该作者
这是个非常大的问题!然后我也解决不了。(有硬件方法和软件方法)真心望高手赐教。

图只看第一个相序图。

普通的编程方法是,A相接外中断,下降沿的时候检查B相,B为高则正转,B为低则反转。
问题就是当编码器刚好正处在A下降沿旁边时,此时风吹一下都会一直抖动(一直产生下降沿),当然单片机就会一直计数。从而产生错误
希望论坛比较有经验的人可以帮忙解决这个问题。(有硬件的方法也有软件的方法)

使用特权

评论回复
8
catiya|  楼主 | 2011-8-19 09:27 | 只看该作者
这是个非常大的问题!然后我也解决不了。(有硬件方法和软件方法)真心望高手赐教。

图只看第一个相序图。

普通的编程方法是,A相接外中断,下降沿 ...
DownCloud 发表于 2011-8-18 20:41



DownCloud兄看来和我遇到了同样的问题。

不过首先不太明白你叙述中提到的“计数”是什么意思?哪里需要计数?

再者,看你的意思,是用编码器直接连接的,所以如果“风吹一下”编码

器就会有微小抖动。但我的实验是模拟的AB相脉冲,不会存在此问题。

如此简单的逻辑,到底问题出在哪?很纳闷。

使用特权

评论回复
9
catiya|  楼主 | 2011-8-19 09:55 | 只看该作者
本帖最后由 catiya 于 2011-8-19 09:59 编辑

dengm同学的程序我试了,还是有问题。另外DB 0,0,0,0有什么用?

我觉得你的程序和我的本质上还是没多大区别吧,都是在外部中断里判断

p3.3口线的电平。

使用特权

评论回复
10
hotpower| | 2011-8-19 10:33 | 只看该作者
6楼邓苗再出江湖!

期待又要“鲜血成河”了!

使用特权

评论回复
11
wang0225| | 2011-8-19 10:34 | 只看该作者
你的硬件在脉冲进入中段口时有没有滤波电容啊?建议用PCA,so easy!

使用特权

评论回复
12
catiya|  楼主 | 2011-8-19 10:40 | 只看该作者
你的硬件在脉冲进入中段口时有没有滤波电容啊?建议用PCA,so easy!
wang0225 发表于 2011-8-19 10:34


没有任何措施。

使用特权

评论回复
13
love_gerry| | 2011-8-19 10:41 | 只看该作者
学习了!

使用特权

评论回复
14
wang0225| | 2011-8-19 10:45 | 只看该作者
你可以加1NF的电容在中端口试下看稳定不?我之前就是这样解决的!

使用特权

评论回复
15
catiya|  楼主 | 2011-8-19 10:46 | 只看该作者
本帖最后由 catiya 于 2011-8-19 10:48 编辑

dengm同学的程序,我分析了一下,还没太明白:

EX_INT0:

        push acc
   
        DB 0,0,0,0 //这句什么意思?
   
        mov a,p3
   
        anl a,#00001100b //正转:p3.2为0,p3.3为0,与得a = 0
                                      //反转:p3.2为0,p3.3为1,与得a = 00001000b
        jz L_INT_10 //若a = 0,则判为正转,将F_DIR置为高
      
        xrl a,#00000100b //若a = 00001000b,则与00000100b异或,a的值为00001100b
      
        jnz L_INT_8 //若a = 00001100b,则退出,否则置F_DIR为低,
                           //但是既然a = 00001100b了,还可能为0吗?F_DIR能被置为低吗?
        clr  F_DIR

L_INT_8:
        
        pop acc
         
        reti

L_INT_10:
                  
        setb F_DIR                  
        
        pop acc
   
        reti

使用特权

评论回复
16
wang0225| | 2011-8-19 10:53 | 只看该作者
DB 0,0,0,0 //这句什么意思?
定义字节变量db = define byte
dw = define word
dd = define dword

使用特权

评论回复
17
jrcsh| | 2011-8-19 11:45 | 只看该作者
sbit aaa=P3^6;//PHA
sbit bbb=P3^7; //PHB


if(aaa==0)
{
aaa1++;
aaa2=0;
}
if(bbb==0)
{
bbb1++;
}
if(aaa2==0)
{
if(aaa==1)
{
if(aaa1>bbb1)
{
ccc=1;//up
aaa1=0;
bbb1=0;
aaa2=1;
}
if(bbb==1)
{
if(bbb1>aaa1)
{
ccc=2;//DO
aaa1=0;
bbb1=0;
aaa2=1;
}
}
}
}



没编译过~~~~ 大搞这会这样搞~~~~ 哈哈

这个方法因当还能在简化简化~~~

使用特权

评论回复
18
catiya|  楼主 | 2011-8-19 13:04 | 只看该作者
DB 0,0,0,0 //这句什么意思?
定义字节变量db = define byte
dw = define word
dd = define dword
wang0225 发表于 2011-8-19 10:53


我意思是,放在这里有什么用?

使用特权

评论回复
19
catiya|  楼主 | 2011-8-19 13:25 | 只看该作者
你可以加1NF的电容在中端口试下看稳定不?我之前就是这样解决的!
wang0225 发表于 2011-8-19 10:45


试过了,还是不行。

使用特权

评论回复
20
wang0225| | 2011-8-19 13:27 | 只看该作者
那你在查下别的原因吧

使用特权

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

本版积分规则

45

主题

228

帖子

2

粉丝