打印

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

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

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

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

相关帖子

沙发
NE5532| | 2011-8-17 20:09 | 只看该作者
拿示波器双踪跟踪,看什么地方出了问题。

使用特权

评论回复
板凳
catiya|  楼主 | 2011-8-18 09:38 | 只看该作者
示波器两通道都同时看了,波形很好。

使用特权

评论回复
地板
NE5532| | 2011-8-18 20:27 | 只看该作者
我是说拿个空闲端口跟踪程序,送出来双踪看。

使用特权

评论回复
5
wy3383818| | 2012-8-14 16:58 | 只看该作者
1# catiya


我也遇到了1L同样的问题,不知道1L解决了没有。这样做理论上是没啥问题的,而且看波形也很清晰,感觉应该不存在抖动的问题,现在就是不知道问题出在哪了,找不到原因就没办法解决。

使用特权

评论回复
6
wy3383818| | 2012-8-14 17:03 | 只看该作者
把我的程序贴出了,大家帮我看看有没有问题?
void interrupt isr(void)
{
        if(TMR0IF)                                                //定时器0中断处理
        {
                TMR0IF = 0;
                TMR0DSP();
                INTF = 0;
        }
        if(INTF)                                                //外部中断处理
        {
                INT_Previous_Count++;                                        //扔掉前3次波形
                if((Encoder_Detect_Tmr == 0)&&(INT_Previous_Count>=3))
                {
                        Encoder_Detect_Tmr = Rotation_Tmr;        //200mS检测间隔
                        INTE = 0;                                                //检测间隔时间内不再进入INT中断
                        INT_Previous_Count = 0;
                        if(EncoderB)                                                // EncoderB电平触发EncoderA电平判断
                        {
                                if(PWM_DATA_Temp >= 12)
                                {
                                        PWM_DATA_Temp = PWM_DATA_Temp-12;
                                }                                        // 逆时针旋转
                                else
                                {
                                        PWM_DATA_Temp = 0;
                                }
                        }
                        if(EncoderB == 0)
                        {
                                if(PWM_DATA_Temp < 0x180)
                                {
                                        PWM_DATA_Temp =PWM_DATA_Temp+12;
                                }                                        //顺时针旋转
                                else
                                {
                                        PWM_DATA_Temp = 0x180;
                                }       
                        }       
                }
                INTF = 0;       
        }
}

使用特权

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

本版积分规则

45

主题

228

帖子

2

粉丝