打印

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

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

实验方法:外部中断法,对编码器输出的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。

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

相关帖子

沙发
westsfw| | 2011-8-25 10:34 | 只看该作者
你查下资料,看在外部中断允许之前,是不是已经置位了中断标志(达到中断条件的话),如果是这样的话,你允许了中断即出程序之后立即响应中断,那查询到的A相的状态就是随机的的嘛,就看你中断允许的时间了。

使用特权

评论回复
板凳
airwill| | 2011-8-27 11:10 | 只看该作者
没有给出 uart_rx()  的实现程序. 我怀疑这个程序的延时太长导致 int0 中断后由于 ex0 没有打开而不能响应, 而当 ex0 打开时,  编码器又转过了角度导致 p3.3 已经发生翻转. 于是错判转向.
楼主不妨换个思路, 不要关 EX0, 每次中断时设个标志(比如正向1,反向0), 也可以把这个标志发给电脑. 在电脑显示屏上看转向判断.

使用特权

评论回复
地板
catiya|  楼主 | 2011-8-27 18:15 | 只看该作者
你查下资料,看在外部中断允许之前,是不是已经置位了中断标志(达到中断条件的话),如果是这样的话,你允许了中断即出程序之后立即响应中断,那查询到的A相的状态就是随机的的嘛,就看你中断允许的时间了。 ...
westsfw 发表于 2011-8-25 10:34


你是说中断请求标志IE0吧,没有任何操作啊,应该不是这个原因吧,

以前很多程序都是这样用的啊,没有什么异常。

使用特权

评论回复
5
catiya|  楼主 | 2011-8-27 18:17 | 只看该作者
没有给出 uart_rx()  的实现程序. 我怀疑这个程序的延时太长导致 int0 中断后由于 ex0 没有打开而不能响应, 而当 ex0 打开时,  编码器又转过了角度导致 p3.3 已经发生翻转. 于是错判转向.
楼主不妨换个思路, 不要关  ...
airwill 发表于 2011-8-27 11:10


uart_rx:

  jnb ri,$
  
  mov a,sbuf
  
  clr ri
        
  ret

使用特权

评论回复
6
catiya|  楼主 | 2011-8-27 18:21 | 只看该作者
我是查询方式接收串口字符,也就是说主程序一直在判ri,当有字符输入(“0xcd”)时,就打开ex0,此时如果来一个int0中断,就响应。

使用特权

评论回复
7
airwill| | 2011-8-29 08:17 | 只看该作者
那么问题真好和我  3楼的猜测一致的.
   jnb ri,$
这条指令可能会消耗非常长的时间才能跳过去. 因为它要接收到数据才能往下走的.
想不消耗时间, 你可以这样写.
uart_rx:
  jnb ri, u_r_end
    mov a,sbuf
    clr ri
u_r_end:   ret

不过这回打乱你的原有程序的规划.
另外:
程序关键部分:
......

acall uart_rx //接收串口字符

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

acall CheckDIR
......

这里头上和尾上的省略部分还有很费时的事情在做也是可能的.
所以最好楼主如 3 楼, 换个思路来写这个程序.

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
catiya + 1
8
yewuyi| | 2011-8-29 11:47 | 只看该作者
如果转速不快的话,俺都用读端口的方式直接把AB信号一起读过来。。。

使用特权

评论回复
9
catiya|  楼主 | 2011-8-29 14:53 | 只看该作者
最快的时候,编码器脉冲超过30k。

使用特权

评论回复
10
catiya|  楼主 | 2011-8-29 14:59 | 只看该作者
按照airwill的思路,没有关ex0,果然有效。

但是7楼的串口写法确实不实用。要么就用中断接收了。

使用特权

评论回复
11
catiya|  楼主 | 2011-8-29 16:00 | 只看该作者
本帖最后由 catiya 于 2011-8-29 16:29 编辑

仔细测试了一下,脉冲频率达到40k的时候,可以判准。

使用特权

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

本版积分规则

45

主题

228

帖子

2

粉丝