打印

PIC单片机 旋转编码器鉴相问题

[复制链接]
4663|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lx911gt|  楼主 | 2013-6-17 16:24 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
沙发
apple| | 2013-6-17 17:35 | 只看该作者
原理和以前机械鼠标类似,两路信号A,B, 在A上升沿时,采样B,B为高或低表示正反转。

使用特权

评论回复
板凳
lx911gt|  楼主 | 2013-6-19 09:19 | 只看该作者
apple 发表于 2013-6-17 17:35
原理和以前机械鼠标类似,两路信号A,B, 在A上升沿时,采样B,B为高或低表示正反转。 ...

我尝试过用TMR0的T0CKI做输入,结果采集到的脉冲根本就飞的不着边了...
麻烦你能把你的程序给我看下吗?谢啦

使用特权

评论回复
地板
lx911gt|  楼主 | 2013-6-19 09:20 | 只看该作者
是这个问题太简单了么?????

没人多少人浏览.................

使用特权

评论回复
5
gonggu8181| | 2013-7-1 23:07 | 只看该作者
用D触发器很简单

使用特权

评论回复
6
dqyubsh| | 2013-7-2 07:06 | 只看该作者
除非成本要求非常苛刻,个人不建议直接接编码器,主要问题是响应速度受限。你至少得评估一下每圈输出多少个脉冲,以及最大转速,看看单片机能否可靠响应。

可以用硬件电路将两路脉冲转换成实现一路脉冲,一路方向,再进单片机,这样难度小很多。或者直接上硬件计数器,或者带编码器计数的芯片,如个别单片机和DSP。

使用特权

评论回复
7
wangch_sh| | 2013-7-2 11:48 | 只看该作者
用定时中断,在中断里判断上升或者下降沿。

使用特权

评论回复
8
lx911gt|  楼主 | 2013-7-6 11:21 | 只看该作者
gonggu8181 发表于 2013-7-1 23:07
用D触发器很简单

我现在用的是D触发器,但是出现个问题,在旋转的时候如果卡在上升沿或下降沿的时候,T0中断会一直响应,计数器就一直加...这个问题要怎么解决?

使用特权

评论回复
9
lx911gt|  楼主 | 2013-7-6 11:21 | 只看该作者
wangch_sh 发表于 2013-7-2 11:48
用定时中断,在中断里判断上升或者下降沿。

麻烦能给个程序么?参考一下:lol

使用特权

评论回复
10
lx911gt|  楼主 | 2013-7-6 11:23 | 只看该作者
dqyubsh 发表于 2013-7-2 07:06
除非成本要求非常苛刻,个人不建议直接接编码器,主要问题是响应速度受限。你至少得评估一下每圈输出多少个 ...

你说的硬件是不是用D触发器做鉴相?然后用单片机计脉冲 ?我现在就是这么做的,但是遇到了问题,在旋转的时候如果卡在上升沿或下降沿的时候,T0中断会一直响应,计数器就一直加...这个问题要怎么解决?

使用特权

评论回复
11
gonggu8181| | 2013-7-7 11:14 | 只看该作者
lx911gt 发表于 2013-7-6 11:21
麻烦能给个程序么?参考一下

TO计时,T1计数。你用应该是脉冲直接控制T0使能吧?

使用特权

评论回复
12
gonggu8181| | 2013-7-7 11:16 | 只看该作者
lx911gt 发表于 2013-7-6 11:21
麻烦能给个程序么?参考一下


使用特权

评论回复
13
gonggu8181| | 2013-7-7 11:17 | 只看该作者
lx911gt 发表于 2013-7-6 11:21
麻烦能给个程序么?参考一下
#include<STC12C2052AD.h>
#include<intrins.h>         
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<absacc.h>                     
#define   uchar  unsigned char                               
#define   ulong  unsigned long
#define   uint   unsigned int                       
#define _Nop() _nop_()         /*定义空指令*/
void sendbyte(uchar byte);
void Disp();

//显示部分
sbit CLK=P1^0;                //定义A串行数据输入端   
sbit DAT=P3^7;                //定义A控制端                 
                                                         
sbit vol=P1^1;                        //
sbit crt=P1^2;          

uchar i=0;
bit flag=0;
uchar count;         //计数
ulong pinlv=0,pin=0;   //频率——频率缓存  
uchar temp[4]=0;          //数据缓存
uchar DispBuf[4]=0;            //4位数据显示

uchar dis_code[10]={
                      0x03,  //"0"
                0x9F,  //"1"
                0x25,  //"2"
                0x0D,  //"3"
                0x99,  //"4"
                0x49,  //"5"
                0x41,  //"6"
                0x1F,  //"7"
                0x01,  //"8"
                0x09   //"9"
};

//延时
void delay_50ms(unsigned int t)
{
unsigned int j;   
for(;t>0;t--)
   for(j=6245;j>0;j--)
{;}
}       
void sendbyte(uchar byte)
{   
                uchar num,c;
                num=dis_code[byte];
                for(c=0;c<8;c++)
                {
                        CLK=0;
                        DAT=num&0x01;
                        CLK=1;
                        num>>=1;   
                }          
}

void time0(void) interrupt 1   //定时器0溢出中断模式2可重装载
{
        TR0=0;                        //定时器0暂停  
        count++;   
        TL0 = 0xB0;                //设置定时初值
        TH0 = 0x3C;                //设置定时初值
        if(count==1)
        {
                Disp();//        LED2=!LED2;
                if(vol==0)
                {
                        delay_50ms(10);
                        if(vol==0)
                        {
                                crt=0;
                        }           
                }
                else crt=1;   
        }                                         
        if(count==20)
        {       
                TR1=0;          //T1计数停止
                count=0;
                TR1=0;                        //定时器1停止计数
                pinlv=TH1*256+TL1;           //计算频率值
                pin=pinlv;                                             
                TH1=0;                                           //计数清零
                TL1=0;
                TR1=1;                                        //开始计数          
         }  
        TR0=1;
}
void Disp()
{                                                                           
        pin=pin*0.06;// (pin/1000)*60 1000线            
        temp[3]=pin/1000%10;            //千位
        temp[2]=pin/100%10;                //百位
        temp[1]=pin%100/10;         //十位
        temp[0]=pin%10;             //个位                  
//        if(temp[4]>=1)
//        {
//                sendbyte(temp[1]);
//                sendbyte(temp[2]);
//                sendbyte(temp[3]);
//                sendbyte(temp[4]);
//        }
//        else  
        sendbyte(temp[0]);
        sendbyte(temp[1]);
        sendbyte(temp[2]);
        sendbyte(temp[3]);                          
}
void init()        //定时器0,1初始化
{
                                                                          
        EA=0;                          //关主中断
        TMOD=0x51;                  //方式寄存器,T0定时,T1计数功能
        TH0=0x3c;                                  //0x3c 定时50ms
        TL0=0xb0;                                   //0xb0
        TH1=0;
        TL1=0;
        ET0=ET1=1;      //T0允许中?       
        EA=1;           //开主中断
        TR1=1;          //T1计数
        TR0=1;              //T0定                 
}  
int main()
{                                                                                                            
        init();            
        while(1);          
}

使用特权

评论回复
14
gonggu8181| | 2013-7-7 11:19 | 只看该作者
误差1/1000左右,晶振20M最好,单片机STC12/STC15系列的都可以。

使用特权

评论回复
15
lx911gt|  楼主 | 2013-7-8 12:19 | 只看该作者
gonggu8181 发表于 2013-7-7 11:19
误差1/1000左右,晶振20M最好,单片机STC12/STC15系列的都可以。

3Q~~~~

使用特权

评论回复
16
mojingjian| | 2017-3-18 09:00 | 只看该作者
路过,现在要用PIC18F4431来写编码器,求解

使用特权

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

本版积分规则

16

主题

62

帖子

0

粉丝