找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3038|回复: 12
收起左侧

在使用单片机+EC11编码器中遇到的问题,请大家帮忙

[复制链接]
ID:388477 发表于 2020-7-9 14:27 | 显示全部楼层 |阅读模式
我想使用编码器控制数码管值的加减,一直没有反应,望高手指教,非常感谢!
#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器


typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;


sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit EC11_A=P2^5;
sbit EC11_B=P2^6;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                                        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u8 d=125;
/*******************************************************************************
* 函 数 名         : delay
* 函数功能                   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
        while(i--);        
}


/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能                   : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigDisplay()
{
        u8 i;
        for(i=0;i<3;i++)
        {
                switch(i)         //位选,选择点亮的数码管,
                {
                        case(0):
                                LSA=0;LSB=0;LSC=0; P0=smgduan[d%10];delay(100); P0=0x00;  break;//显示第0位
                        case(1):
                                LSA=1;LSB=0;LSC=0; P0=smgduan[d%100/10];delay(100);P0=0x00; break;//显示第1位
                        case(2):
                                LSA=0;LSB=1;LSC=0; P0=smgduan[d/100];delay(100);P0=0x00;    break;//显示第2位


                }
        
        }
}


void xuanzhun()
{
        u8 flag=0,left_flag=0,right_flag=0;
        if((EC11_A)&&(EC11_B))
                {
                                flag=1;
                }
                if(EC11_A!=EC11_B)
                {
                                left_flag = EC11_A; //记录AB的信号状态
                                right_flag = EC11_B;
                }
                if(flag==1)
                {
                                if((EC11_A==0)&&(EC11_B==0))
                                {
                                                flag=0;
                                                if(left_flag==0)  //左转
                                                {
                                                                d--;
                                                }
                                                if(right_flag==0)
                                                {
                                                                d++;
                                                }
                                }        
                }
}




/*******************************************************************************
* 函 数 名       : main
* 函数功能                 : 主函数
* 输    入       : 无
* 输    出             : 无
*******************************************************************************/
void main()
{        
        while(1)
        {
                xuanzhun();
                DigDisplay();  //数码管显示函数        
        }        
}

回复

使用道具 举报

ID:401564 发表于 2020-7-9 15:12 | 显示全部楼层
马云家的EC11有好几种的:有20位和30位的
这其中又分为好几种开关状态的:1是转动之后固定在短路状态的,一种是固定在开路状态的,还有一个是每次转动停止之后不固定的
所以,你得看你手头上这个开关的规格书还写代码,完全复制别人的代码不一定行的
回复

使用道具 举报

ID:282850 发表于 2020-7-9 16:26 | 显示全部楼层
是否对你有用,IO口中断判定输入

//旋转编码开头,测试与网上介绍相符:
//按下时4、5导通,4、5不与其它脚内部相关
//                 ______
//P25    A     1--|   /|--4 (Press)
//P24    com   2--|__/ |
//P26    B     3--|____|--5 (Press)      P27
//顺时针转:Aon--ABon--Aoff--Boff
//逆时针转:Bon--ABon--Boff--Aoff
//时序图如下(设com接Vcc):
//顺时针A-->B转
//A      ____     ____
//      |  |___|  |_
//B        ____     ____
//        |  |___|  |_


//
//逆时针B-->A转
//B      ____     ____
//      |  |___|  |_
//A        ____     ____
//        |  |___|  |_
//程序思路:
//为与C51兼容,少点用中断口线,仅使用A线的中断进行判断,B线不考虑
//Aon中断---if(Boff)----是A2B--- 计数+
//          if(Bon)-----是B2A--- 计数-
//Aon中断,反转Aoff---if(Boff)----是A2B--- 计数+
//                    if(Bon)-----是B2A--- 计数-
//有旋转,注先转到B但A没on时(半格不到),丢弃

#pragma vector=PORT2_VECTOR
__interrupt void Port2_IR2(void)
{
      //    PressTime=0;
      if(P2IFG & Aon)  //有右旋转
      {
            P2IFG=0;   
            if(P2IN & Bon) keyOld=keyN, keyN++;  //
      }
      
      if(P2IFG & Bon)  //有左旋转
      {
            P2IFG=0;   
            if(P2IN & Aon)  keyOld=keyN, keyN--; //
      }
      if(P2IFG & downKey)  //有按下
      {
            P2IFG=0;
            keyPress();
      }
      P2IFG=0;
      
      HT16_DisplayDecimal(keyN,0);
      HT16_1NumDOT(3,Menu_sel,0);
      //__low_power_mode_off_on_exit();     //退出中断时唤醒CPU。▲▲▲▲在此退LPM,比在BT中断中退更省电 ▲▲▲▲可运行60+20秒!!
}
回复

使用道具 举报

ID:388477 发表于 2020-7-9 16:53 | 显示全部楼层
Y_G_G 发表于 2020-7-9 15:12
马云家的EC11有好几种的:有20位和30位的
这其中又分为好几种开关状态的:1是转动之后固定在短路状态的,一种 ...

嗯嗯,我刚接触这个是照一个视频写的,我觉得挺好理解,我现在这个是24位的,整了好长时间,希望给点思路或者参考,谢谢
回复

使用道具 举报

ID:799404 发表于 2020-7-9 17:02 | 显示全部楼层
显示部分正常吗,先排查下改变d的值以后显示会变化吗
回复

使用道具 举报

ID:799404 发表于 2020-7-9 17:10 | 显示全部楼层
LSA/LSB/LSC是位码吧,数码管case0的时候没有点位码呢
回复

使用道具 举报

ID:388477 发表于 2020-7-9 19:06 | 显示全部楼层
wjianing 发表于 2020-7-9 17:02
显示部分正常吗,先排查下改变d的值以后显示会变化吗

改变d的之后,会改变,谢谢!
回复

使用道具 举报

ID:388477 发表于 2020-7-9 19:09 | 显示全部楼层
wjianing 发表于 2020-7-9 17:10
LSA/LSB/LSC是位码吧,数码管case0的时候没有点位码呢

是位码,可以显示
回复

使用道具 举报

ID:401564 发表于 2020-7-9 20:14 | 显示全部楼层
C不会,我用汇编的
但原理是一样的:就是每次转动就把两个端口的电平记录,读取到某个数据的时候就判定为左转还是右转
你把数据手册上的时序好好的看一下就知道,它顺时针和逆时针的区别在于哪个先出现电平的变化
最好是用定时器,一般2mS扫描一次就可以了
回复

使用道具 举报

ID:388477 发表于 2020-7-10 11:09 | 显示全部楼层
f556 发表于 2020-7-9 16:26
是否对你有用,IO口中断判定输入

//旋转编码开头,测试与网上介绍相符:

没有看懂,谢谢你
回复

使用道具 举报

ID:388477 发表于 2020-7-11 14:45 | 显示全部楼层
终于搞定了,又换了一个ec11的编码器,20节点的,程序经测试,普中v2.0的板子,一个节点加一或者减一,谢谢大家的帮忙!

#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit BMA=P1^0;
sbit BMB=P1^1;
sbit button=P1^2;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                                        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u16 d=235;
u8 flag;
u8 b,Last_BMB_status,Current_BMB_status;
///*******************************************************************************
//* 函 数 名         : delay
//* 函数功能                   : 延时函数,i=1时,大约延时10us
//*******************************************************************************/
void delay(u16 i)
{
        while(i--);       
}
/*******************************************************************************
* 函 数 名         : DigDisplay
* 函数功能                   : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigDisplay()
{
        u8 i;
        for(i=0;i<3;i++)
        {
                switch(i)         //位选,选择点亮的数码管,
                {
                        case(0):
                                LSA=0;LSB=0;LSC=0; P0=smgduan[d%10];delay(100); P0=0x00;  break;//显示第0位
                        case(1):
                                LSA=1;LSB=0;LSC=0; P0=smgduan[d%100/10];delay(100);P0=0x00; break;//显示第1位
                        case(2):
                                LSA=0;LSB=1;LSC=0; P0=smgduan[d/100];delay(100);P0=0x00;    break;//显示第2位
                }
        }
}

void DirScan(void)
{
                Last_BMB_status = BMB;
    if(BMA == 0)    //BMA为低电平时
    {
                                while(!BMA);
        Current_BMB_status = BMB;
        flag = 1;    //标志位置为1说明编码开关被旋转了
                                if(flag == 1)
                                {  
                                                flag = 0;    //时刻要注意这一点!给标志位清零
                                                if(Current_BMB_status == 1) //BMB上升沿表示正转
                                                {
                                                                d++;
                                                                if(d>=999)  d=999;       
                                                }
                                                else if((Last_BMB_status == 1)&&(Current_BMB_status == 0)) //BMB下降沿表示反转
                                                {
                                                                d--;
                                                                if(d==65535) d=0;
                                                }
                                }
    }
                if(button==0)
                {
                                delay(10);
                                if(button==0)
                                        d=0;
                }
}

void main()
{
        while(1)
        {
                        DirScan();
                        DigDisplay();  //数码管显示函数               
        }       
}

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:611626 发表于 2021-9-1 10:08 | 显示全部楼层
case(0):
                                LSA=0;LSB=0;LSC=0; P0=smgduan[d%10];delay(100); P0=0x00;  break;//显示第0位
                        case(1):
                                LSA=1;LSB=0;LSC=0; P0=smgduan[d%100/10];delay(100);P0=0x00; break;//显示第1位
                        case(2):
                                LSA=0;LSB=1;LSC=0; P0=smgduan[d/100];delay(100);P0=0x00;    break;//显示第2位
                }
你用的共阴数码管,这样能显示正常吗
回复

使用道具 举报

ID:161164 发表于 2021-9-1 10:51 | 显示全部楼层
宏达工控 发表于 2021-9-1 10:08
case(0):
                                LSA=0;LSB=0;LSC=0; P0=smgduan[d%10];delay(100); P0=0x00;   ...

可能共阴段接了一个NPN反相圹流
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表