找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4023|回復(fù): 14
打印 上一主題 下一主題
收起左側(cè)

ec11編碼器誰(shuí)有好用的單片機(jī)代碼?現(xiàn)在抖動(dòng)嚴(yán)重,亂跳 中斷方式也步進(jìn)丟失

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:34268 發(fā)表于 2022-5-7 18:41 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
ec11編碼器誰(shuí)有好用的代碼共享一下,現(xiàn)在的代碼抖動(dòng)嚴(yán)重,亂跳。用過(guò)中斷方式也不好用,一樣會(huì)出現(xiàn)步進(jìn)丟失。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏7 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:94031 發(fā)表于 2022-5-7 19:13 | 只看該作者
要在硬件上下功夫。
回復(fù)

使用道具 舉報(bào)

板凳
ID:149451 發(fā)表于 2022-5-7 19:27 | 只看該作者
看看下面這個(gè)程序,我把它改在控制LED流水方向上,OK的。注意EC11幾個(gè)端子的電容是防抖動(dòng)。
// Header:  編碼開(kāi)關(guān)代碼   
// File Name: Encoder   
// Author:  李波   
// Date: 2009-04-19  20161129在開(kāi)發(fā)板上完美運(yùn)行:通過(guò)編碼器EC11控制流水燈流動(dòng)
/*========================================  
本代碼為編碼開(kāi)關(guān)代碼,編碼開(kāi)關(guān)也就是數(shù)字音響中的  
360度旋轉(zhuǎn)的數(shù)字音量以及顯示器上用的(單鍵飛梭開(kāi)  
關(guān))等類(lèi)似鼠標(biāo)滾輪的手動(dòng)計(jì)數(shù)輸入設(shè)備。  
我使用的編碼開(kāi)關(guān)為5個(gè)引腳的,其中2個(gè)引腳為按下  
轉(zhuǎn)輪開(kāi)關(guān)(也就相當(dāng)于鼠標(biāo)中鍵)一個(gè)接地,另一個(gè)P3.4。另外3個(gè)引腳用來(lái)  
檢測(cè)旋轉(zhuǎn)方向以及旋轉(zhuǎn)步數(shù)的檢測(cè)端。引腳分別為a,b,c  
b接地;a,c分別接到P3.3和P3.2口并分別接兩個(gè)10K上拉  
電阻,并且a,c需要分別對(duì)地接一個(gè)104的電容,否則  
因?yàn)榫幋a開(kāi)關(guān)的觸點(diǎn)抖動(dòng)會(huì)引起輕微誤動(dòng)作。本程序不  
使用定時(shí)器,不占用中斷,不使用延時(shí)代碼,并對(duì)每個(gè)  
細(xì)分步數(shù)進(jìn)行判斷,避免一切誤動(dòng)作,性能超級(jí)穩(wěn)定。  
我使用的編碼器是APLS的EC11可以參照附件的時(shí)序圖  
編碼器控制流水燈最能說(shuō)明問(wèn)題,下面是以一段流水  
燈來(lái)演示。  
(單片機(jī)為STC89C52)=================*/   
#include <REGX52.H>   
#include <intrins.h>   
#define uint unsigned int   
#define uchar unsigned char   
#define NULL 0   

uchar x,WheelOld;   
uchar Led=0xfe;//LED流水燈初始化   

sbit SJ=P1^4;       //LED的使能端  YY開(kāi)發(fā)板特有
sbit WEI=P2^1;      //74HC573的LE端 U4 LED的位選端 YY開(kāi)發(fā)板特有,熄滅數(shù)碼管
   
/*定義一下端口為編碼器開(kāi)關(guān)輸入端=========*/   
sbit PINA=P3^2;    //定義編碼器連接的IO   
sbit PINB=P3^3;    //定義編碼器連接的IO   
   
/*過(guò)程返回==========*/   
uchar WheelLeft()      
{      
     //左轉(zhuǎn)一步的操作   
        Led=_crol_(Led,1);         
    return(NULL);      
}     

uchar WheelRight()      
{      
     //右轉(zhuǎn)一步的操作   
     Led=_cror_(Led,1);   
     return(NULL);      
}     
   
/*編碼器過(guò)程====================*/   
uchar EncoderProcess()   
{      
     uchar keytmp,keytmp1,keytmp2,WheelNow;   
   
     PINA=1; //PINA至高電平   
     PINB=1;//PINB至高電平   
     if(PINA==1) //如果PINA為高電平   
         {   
         keytmp1=0x01;   
         }   
     else keytmp1=0;     
     if(PINB==1) //如果PINB為高電平   
         {   
         keytmp2=0x02;   
         }   
     else keytmp2=0;   
     WheelNow=keytmp1+keytmp2; //根據(jù)兩個(gè)IO組合成16進(jìn)制數(shù)為0x00|0x01|0x02|0x03   
     keytmp=WheelNow;   
     keytmp^=WheelOld;  //判斷新數(shù)據(jù)同舊數(shù)據(jù)   
     if(keytmp==0) return(NULL); //如果新數(shù)據(jù)和原來(lái)的數(shù)據(jù)一樣 就直接退出   
     if(WheelOld==0 && WheelNow==0x01)   
         {   
         x=WheelNow;   
         }   
   
     if(WheelOld==0 && x==0x01 && WheelNow==0x03)   
         {   
         WheelOld=WheelNow;   
         x=0;   
         return(WheelLeft()); //左旋轉(zhuǎn)00 01 03   
         }   
   
     if(WheelOld==0x03 && WheelNow==0x02)   
         {   
         x=WheelNow;   
         }   
   
     if(WheelOld==0x03 && x==0x02 && WheelNow==0x00)   
         {   
         WheelOld=WheelNow;   
         x=0;   
         return(WheelLeft()); //左旋轉(zhuǎn)03 02 00   
         }   
   
     if(WheelOld==0 && WheelNow==0x02)   
         {   
         x=WheelNow;   
         }   
   
     if(WheelOld==0 && x==0x02 && WheelNow==0x03)   
         {   
         WheelOld=WheelNow;   
         x=0;           
         return(WheelRight());  //右旋轉(zhuǎn)00 02 03   
         }   
   
     if(WheelOld==0x03 && WheelNow==0x01)   
         {   
         x=WheelNow;   
         }   
   
     if(WheelOld==0x03 && x==0x01 && WheelNow==0x00)   
         {   
         WheelOld=WheelNow;   
         x=0;      
         return(WheelRight());  //右旋轉(zhuǎn)03 01 10   
         }   
   
}   

void main()   
{      
        SJ=0;        //開(kāi)LED總使能 YY開(kāi)發(fā)板特有   
    WEI=1;
        P0=0xff;
        WEI=0;   
    while (1)   
    {   
            EncoderProcess();   
            P0=Led; //流水燈連接的IO   
    }   
}
回復(fù)

使用道具 舉報(bào)

地板
ID:34268 發(fā)表于 2022-5-7 20:19 | 只看該作者
我天代碼這么長(zhǎng)。
回復(fù)

使用道具 舉報(bào)

5#
ID:624769 發(fā)表于 2022-5-7 20:56 | 只看該作者


  1. <p>sbit INT0 = P3^2;  //EC11 PinA
  2. sbit INT1 = P3^3;  //EC11 PinB
  3. unsigned char KeyValue;</p><p>
  4. </p><p>void main()
  5. {
  6. INT0 = 1;
  7. INT1 = 1;
  8. IE0 = 0;
  9. IE1 = 0;
  10. IT0 = 1;
  11. IT1 = 1;
  12. EX0 = 1;
  13. EX1 = 1;
  14. EA = 1;
  15. while(1);</p><p>}</p><p>
  16. void EC11_Reset()   //消抖
  17. {
  18. unsigned char i;
  19. while((IE0)||(IE1)||(!INT0)||(!INT1)) //等待 INT0, INT1 無(wú)抖動(dòng)高電平
  20. {
  21.   IE0 = 0;
  22.   IE1 = 0;
  23.   i = 200; //根據(jù)需要定義
  24.   while(--i);
  25. }
  26. }</p><p>void EX_INT_0() interrupt 0
  27. {
  28. while(INT1);  //等待 INT1 低電平
  29. EC11_Reset();  //等待 EC11 回初始狀態(tài)
  30. KeyValue++;
  31. }</p><p>void EX_INT_1() interrupt 2
  32. {
  33. while(INT0);  //等待 INT0 低電平
  34. EC11_Reset();  //等待 EC11 回初始狀態(tài)
  35. KeyValue--;
  36. }</p>
復(fù)制代碼
優(yōu)點(diǎn):開(kāi)關(guān)未旋轉(zhuǎn)時(shí),不占用系統(tǒng)資源。
缺點(diǎn):旋轉(zhuǎn)時(shí)比較占用系統(tǒng)資源。
建議:如經(jīng)常旋轉(zhuǎn),并且系統(tǒng)比較繁忙,可以加定時(shí)器,編碼器觸發(fā)中斷后,先關(guān)閉外部中斷,通過(guò)定時(shí)器來(lái)等待編碼器復(fù)位后,重開(kāi)外部中斷。


回復(fù)

使用道具 舉報(bào)

6#
ID:213173 發(fā)表于 2022-5-7 20:59 | 只看該作者
  1. //測(cè)試條件:TX-1C開(kāi)發(fā)板
  2. //杜邦線(xiàn)直接連接ABC端,未接消抖電容
  3. //正常快慢手速未見(jiàn)誤碼
  4. #include "reg51.h"

  5. typedef unsigned char uchar;
  6. typedef unsigned int  uint;

  7. sbit EC11_A=P3^2;
  8. sbit EC11_C=P3^3;
  9. sbit EC11_B=P3^4;

  10. sbit dula=P2^6;                                        //段
  11. sbit wela=P2^7;                                        //位
  12. //        共陰數(shù)碼管標(biāo)準(zhǔn)字庫(kù)       
  13. unsigned char code table[32]={                               
  14. //         0    1    2    3    4    5    6    7    8    9   10A  11B  12C  13D  14E  15F
  15.         0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  16. //  16黑  17- 18H   19J         20K  21L  22N        23o  24P  25U  26t 27G   28Q  29r  30M  31y
  17.         0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e};
  18. unsigned char  data dis_buf[4];                        //顯示緩存
  19. unsigned char count=50;
  20. unsigned char traitA,traitB;
  21. void display()
  22. {
  23.         static unsigned char  i;
  24.         P0=0x00;dula=1;dula=0;
  25.         P0=~(0x01<<i);wela=1;wela=0;
  26.         P0=dis_buf[i];dula=1;dula=0;
  27.         i=++i%4;
  28. }

  29. void main()
  30. {
  31.         EC11_C=0;
  32.         while (1)
  33.         {
  34.                 dis_buf[0]=table[17];
  35.                 dis_buf[1]=table[count/100%10];
  36.                 dis_buf[2]=table[count/10%10];
  37.                 dis_buf[3]=table[count%10];
  38.                 display();
  39.                 //順時(shí)針旋轉(zhuǎn),每圈進(jìn)階20
  40.                 if(EC11_B && !EC11_A && traitA==0)          //第一特征碼,如不符合則立即進(jìn)行反轉(zhuǎn)判斷
  41.                 {
  42.                         traitA=1;
  43.                 }
  44.                 else if(!EC11_B && !EC11_A && traitA==1)//第二特征碼
  45.                 {
  46.                         traitA=2;
  47.                 }
  48.                 else if(!EC11_B && EC11_A && traitA==2)//第三特征碼
  49.                 {
  50.                         if(count>0)count--;
  51.                         traitA=3;
  52.                 }
  53.                 else if(EC11_B && EC11_A)//第四特征碼
  54.                 {
  55.                         traitA=0;//清0
  56.                 }
  57.                 //逆時(shí)針旋轉(zhuǎn)
  58.                 if(!EC11_B && EC11_A && traitB==0)          //第一特征碼,如不符合則立即進(jìn)行正轉(zhuǎn)判斷
  59.                 {
  60.                         traitB=1;
  61.                 }
  62.                 else if(!EC11_B && !EC11_A && traitB==1)//第二特征碼
  63.                 {
  64.                         traitB=2;
  65.                 }
  66.                 else if(EC11_B && !EC11_A && traitB==2)//第三特征碼
  67.                 {
  68.                         if(count<250)count++;
  69.                         traitB=3;
  70.                 }
  71.                 else if(EC11_B && EC11_A)//第四特征碼
  72.                 {
  73.                         traitB=0;//清0
  74.                 }
  75.         }
  76. }

復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

7#
ID:161164 發(fā)表于 2022-5-7 23:20 | 只看該作者
szqkfsskk 發(fā)表于 2022-5-7 20:19
我天代碼這么長(zhǎng)。


只有六行,夠短了吧
  1.             if(!PinA && PinA_O && PinB) {

  2.                  Now++;

  3.              }PinA_O = PinA;               

  4.              if(!PinB && PinB_O && PinA) {

  5.                  Now--;

  6.              }PinB_O = PinB;        
復(fù)制代碼




詳情請(qǐng)看我的貼子

回復(fù)

使用道具 舉報(bào)

8#
ID:390416 發(fā)表于 2022-5-7 23:52 | 只看該作者
void ROTARY_ROTARY_Scan_Drive(void)
{
        static xdata u8 count=0,Rotary_Flag=0;
        if(count>30)
        {
                count=0;
                if((ROTARY_B==0)&&(Rotary_Flag==0))                        //如果按鍵B按下,且flag是0       
                {
                        Rotary_Flag=1;
                        Rotary_Read_Data_Rotary++;                                //按鍵值增加1
                }
                if((ROTARY_A==0)&&(Rotary_Flag==0))                        //如果按鍵A按下,且flag是0       
                {
                        Rotary_Flag=1;
                        Rotary_Read_Data_Rotary--;                                //按鍵值減少1
                }
                if((ROTARY_B!=0)&&(ROTARY_A!=0))                        //按鍵必須釋放,下次按鍵才有效
                {
                        Rotary_Flag=0;
                }
        }
        count++;
}

主函數(shù)直接循環(huán)掃描這個(gè)函數(shù)就行了,人人學(xué)會(huì)單片機(jī)!對(duì)付人手還是可以的,如果是光電編碼器 不適合此代碼。
回復(fù)

使用道具 舉報(bào)

9#
ID:401564 發(fā)表于 2022-5-8 09:21 | 只看該作者
lkc8210 發(fā)表于 2022-5-7 23:20
只有六行,夠短了吧

經(jīng)過(guò)燒錄驗(yàn)證,并不行
不用轉(zhuǎn)動(dòng),搖一下EC11的搖桿,NOW就會(huì)改變
轉(zhuǎn)一半,再不轉(zhuǎn),NOW也會(huì)改變
你帖子我看了,波形不需要分析,只看實(shí)際結(jié)果
回復(fù)

使用道具 舉報(bào)

10#
ID:401564 發(fā)表于 2022-5-8 09:24 | 只看該作者
如果單片機(jī)不著急處理太多的東西,可以用定時(shí)器1mS掃描一次AB兩個(gè)IO來(lái)判斷轉(zhuǎn)動(dòng)
不用加電容,不用加去抖動(dòng)
回復(fù)

使用道具 舉報(bào)

11#
ID:161164 發(fā)表于 2022-5-8 10:12 | 只看該作者
Y_G_G 發(fā)表于 2022-5-8 09:21
經(jīng)過(guò)燒錄驗(yàn)證,并不行
不用轉(zhuǎn)動(dòng),搖一下EC11的搖桿,NOW就會(huì)改變
轉(zhuǎn)一半,再不轉(zhuǎn),NOW也會(huì)改變

如果不分析波形,只看實(shí)際結(jié)果
有沒(méi)有可能…
你的實(shí)際和我的實(shí)際有點(diǎn)不一樣?

if(ScanCount++ > 50)//這里有調(diào)大一點(diǎn)嗎?
回復(fù)

使用道具 舉報(bào)

12#
ID:401564 發(fā)表于 2022-5-8 11:12 | 只看該作者
lkc8210 發(fā)表于 2022-5-8 10:12
如果不分析波形,只看實(shí)際結(jié)果
有沒(méi)有可能…
你的實(shí)際和我的實(shí)際有點(diǎn)不一樣?

沒(méi)有調(diào)大,我只是復(fù)制驗(yàn)證一下而已
并不是每次都會(huì)變動(dòng),單純的找BUG一樣去試的話(huà),會(huì)有問(wèn)題
如果只是正常使用,我轉(zhuǎn)了就不再調(diào)回來(lái),那效果還是可以的
回復(fù)

使用道具 舉報(bào)

13#
ID:417804 發(fā)表于 2022-7-1 21:23 | 只看該作者

ytyt 放謝謝,很好用
回復(fù)

使用道具 舉報(bào)

14#
ID:1034178 發(fā)表于 2023-12-7 21:11 來(lái)自手機(jī) | 只看該作者
論證才有進(jìn)步
回復(fù)

使用道具 舉報(bào)

15#
ID:909736 發(fā)表于 2024-8-1 06:34 來(lái)自手機(jī) | 只看該作者
lkc8210 發(fā)表于 2022-5-7 23:20
只有六行,夠短了吧



以前看見(jiàn)過(guò)這個(gè)代碼,后來(lái)就找不到了,謝謝
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表