久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5047|回復: 28
打印 上一主題 下一主題
收起左側

EC11編碼器基于運算解碼的算法(原創)

  [復制鏈接]
跳轉到指定樓層
樓主
EC11編碼器基于運算解碼的算法(原創)

EC11旋轉編碼器是一種基于脈沖發生的裝置,它的編碼邏輯如下圖


單片機解碼方式主要有幾種:
1、MCU定時器自帶編碼器模式,如GD32、STM32等;
2、使用外部IO中斷,在中斷時根據A或B的電平狀態,來確定編碼器的方向并計數;
3、在主程序里循環掃描或定時器中斷掃描的方式;
我現在以第3種掃描算法方面來跟大家分享:
目前網上搜索到的代碼,基本都是以時序AB相的狀態,基于邏輯條件來解碼,如:
  1. char Encoder_EC11_Scan()     /*  這里只是部分代碼  */
  2. {
  3. //以下儲存A、B上一次值的變量聲明為靜態全局變量,方便對EC11對應的IO口做初始化
  4. //  static char EC11_A_Last = 0;
  5. //  static char EC11_B_Last = 0;
  6.     char ScanResult = 0;    //返回編碼器掃描結果,用于分析編碼器的動作
  7.                             //返回值的取值:   0:無動作;      1:正轉;           -1:反轉;  
  8.                             //                  2:只按下按鍵;    3:按著按鍵正轉;   -3:按著按鍵反轉

  9.                             //======================================================//
  10.     if(EC11_Type == 0)      //================一定位對應一脈沖的EC11================//
  11.     {                       //======================================================//
  12.         if(EC11_A_Now != EC11_A_Last)   //以A為時鐘,B為數據。正轉時AB反相,反轉時AB同相
  13.         {
  14.             if(EC11_A_Now == 0)
  15.             {
  16.                 if(EC11_B_Now ==1)      //只需要采集A的上升沿或下降沿的任意一個狀態,若A下降沿時B為1,正轉                    
  17.                     ScanResult = 1;     //正轉

  18.                 else                    //反轉
  19.                     ScanResult = -1;
  20.             }
  21.             EC11_A_Last = EC11_A_Now;   //更新編碼器上一個狀態暫存變量
  22.             EC11_B_Last = EC11_B_Now;   //更新編碼器上一個狀態暫存變量
  23.         }
  24.     }
  25. return ScanResult;      //返回值的取值:   0:無動作;      1:正轉;           -1:反轉;
  26. }
復制代碼
也有lkc8210發表的非常不錯的方法:一定位一脈沖的EC11旋轉編碼器最簡潔的單片機驅動代碼
我通過研究,原創了基于運算解碼的算法,先上代碼
//算法一
uint8_t KeyA_Last;
uint8_t KeyB_Last;
uint8_t KeyA_Now;
uint8_t KeyB_Now;
int EC_Counter;
int EC_CountTemp;

void Encoder_Ini()
{
    KeyA_Last = P10;
    KeyB_Last = P11;
}
void Encoder_Run()
{
    KeyA_Now = P10;
    KeyB_Now = P11;
EC_Counter +=(1 ^ (KeyA_Last ^ KeyB_Last)) * (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)); //更新計數
    KeyA_Last = KeyA_Now;
    KeyB_Last = KeyB_Now;
}



眼尖的網友可以看到,我的掃描解碼程序里并沒有邏輯判斷,EC_Counter計數值會自動解碼加減,什么情況?
我先來解析一下算法:
上次A、B電平相等時,A=1,B=1,或A=0,B=0時,KeyA_Last ^ KeyB_Last的異或運行結果會等于0,這時1^0就變成了1,
這個運算的作用就是如果上次AB相等,就可能會更新EC_Counter的值,因為這個結果后面跟著乘號,如果上次AB不相等時,運算結果為0,0乘以任何數仍為0,
EC_Counter的值就+=0,不變;
A相的電平發生變化時(上升沿或下降沿),KeyA_Last^KeyA_Now運算的結果=1;
A相的電平未發生變化,KeyA_Last^Key_Now運算的結果=0;
同理,B相的電平發生變化時(上升沿或下降沿),KeyB_Last^KeyB_Now運算的結果=1;
B相的電平未發生變化,KeyB_Last^KeyB_Now運算的結果=0;


現以反轉時序來分析,從EC11編碼器的波形可以看出,
反轉時,初始狀態要么A=1 ,B=1,要么A=0,B=0,在此以默認A=1,B=1來舉例計算:
第一步: A=1,B=1,此時 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)= 1^(1^1)=1,
     KeyA_Last^KeyA_Now=1^1=0,
     KeyB_Last^KeyB_Now =1^1=0,
     右邊運算結果:1*(0-0)= 0,即EC_Counter+=0


第二步: A=1,B=0 此時 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=1 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^1)=1,
    KeyA_Last^KeyA_Now=1^1=0,
    KeyB_Last^KeyB_Now =1^0=1,
    右邊運算結果:1*(0-1)= -1,即EC_Counter+= -1;
第三步: A=0,B=0 此時 KeyA_Last=1,  KeyB_Last =0,  KeyA_Now=0 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^0)=0,
    KeyA_Last^KeyA_Now=1^0=1,
    KeyB_Last^KeyB_Now =0^0=0,
    右邊運算結果:0*(1-0)=0,即EC_Counter+=0

第四步: A=0,B=1 此時 KeyA_Last=0,  KeyB_Last =0,  KeyA_Now=0 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^0)=1,
    KeyA_Last^KeyA_Now=0^0=0,
    KeyB_Last^KeyB_Now =0^1=1,
    右邊運算結果:1*(0-1)=-1,即EC_Counter+=-1

第五步: A=1,B=1 此時 KeyA_Last=0,  KeyB_Last =1  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^1)=0,
    KeyA_Last^KeyA_Now=0^1=1,
    KeyB_Last^KeyB_Now =1^1=0,
    右邊運算結果:0*(1-0)=0,即EC_Counter+=0


繼續反轉的話,又到了第二步;


正轉時,初始狀態要么A=1 ,B=1,要么A=0,B=0,在此以A=1,B=1來舉例計算:
第一步: A=1,B=1,此時 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)= 1^(1^1)=1,
     KeyA_Last^KeyA_Now=1^1=0,
     KeyB_Last^KeyB_Now =1^1=0,
     右邊運算結果:1*(0-0)= 0,即EC_Counter+=0


第二步: A=0,B=1 此時 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=0 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^1)=1,
    KeyA_Last^KeyA_Now=1^0=1,
    KeyB_Last^KeyB_Now =1^1=0,
    右邊運算結果:1*(1-0)= 1,即EC_Counter+= 1;
第三步: A=0,B=0 此時 KeyA_Last=0,  KeyB_Last =1,  KeyA_Now=0 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^1)=0,
    KeyA_Last^KeyA_Now=0^0=0,
    KeyB_Last^KeyB_Now =1^0=1,
    右邊運算結果:0*(0-1)=0,即EC_Counter+=0

第四步: A=1,B=0 此時 KeyA_Last=0,  KeyB_Last =0,  KeyA_Now=1 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^0)=1,
    KeyA_Last^KeyA_Now=0^1=1,
    KeyB_Last^KeyB_Now =0^0=0,
    右邊運算結果:1*(1-0)=1,即EC_Counter+=1

第五步: A=1,B=1 此時 KeyA_Last=1,  KeyB_Last =0  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^0)=0,
    KeyA_Last^KeyA_Now=1^1=0,
    KeyB_Last^KeyB_Now =0^1=1,
    右邊運算結果:0*(0-1)=0,即EC_Counter+=0


繼續正轉的話,又到了第二步;

從上面運算可以,公式以雙倍頻(旋轉嘀嗒一格,兩次計數)解碼EC11編碼器;

有網友問,如果我只要單倍頻旋轉嘀嗒一下,單次計數),又怎么解碼?
這時,可以要根據你的編碼器默認電平來改,默認A=1,B=1時,
加個條件即可
if(KeyA_Last==0 && KeyB_Last==0)  //只有上次都為0時(要與默認值相反),才更新計數
{
   EC_Counter += (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)); //計數值運算
}
默認A=0,B=0時,
加個條件即可
if(KeyA_Last==1 && KeyB_Last==1)  //只有上次都為1時(要與默認值相反),才更新計數
{
   EC_Counter += (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)); //計數值運算
}

單倍頻的程序代碼如下:
  1. uint8_t KeyA_Last;
  2. uint8_t KeyB_Last;
  3. uint8_t KeyA_Now;
  4. uint8_t KeyB_Now;
  5. int EC_Counter;
  6. int EC_CountTemp;

  7. void Encoder_Ini()
  8. {
  9.     KeyA_Last = P10;
  10.     KeyB_Last = P11;
  11. }
  12. void Encoder_Run()
  13. {
  14.     KeyA_Now = P10;
  15.     KeyB_Now = P11;
  16.     if(KeyA_Last==1 && KeyB_Last==1)  //注意此處與編碼器默認的電平相
  17.     {
  18.      EC_Counter +=(int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now));//如要調整加減方向,請修改此
  19.     }
  20.     KeyA_Last = KeyA_Now;
  21.     KeyB_Last = KeyB_Now;
  22. }
復制代碼
以上算法是不是很特別?以上代碼我通過了驗證,如果不用定時中斷掃描,正常12格/秒手速旋轉無問題,如果加1ms的定時中斷掃描,80格/秒手速旋轉無問題;編譯后代碼在N76E003里,匯編行數50行,大小增加100byte
如果網友只需要單倍頻,也可以用我下面的算法,匯編行數更少40多行,大小增加72byte,
AB狀態一起處理,具體原理大家去分析

//算法二 編譯最小,但只適合單倍頻
int EC_Counter;
int EC_CountTemp;

uint8_t KeyAB_Last;
uint8_t KeyAB_Now;

void Encoder_Ini()
{
  KeyAB_Last =P1 & 0x03;
}
void Encoder_Run()
{
    uint8_t Temp;
    KeyAB_Now =(P1 & 0x03);
    Temp=KeyAB_Now^KeyAB_Last;
    if(KeyAB_Last==00) //注意此處與編碼器默認的電平相反
    {  
      EC_Counter +=(int)((Temp&0x01)-(Temp>>1)); //如要調整方向,請修改此處
    }
                KeyAB_Last=KeyAB_Now;
}

如果有網友說:你上面單倍頻的算法,忽略了過程中的一部分,會不會有問題?
我可以放心的告訴大家,我驗證的效果和算法一效果相當,可以使用,當然如果你不放心,我還有一種就是把所有的步驟都考慮進去的算法,如下:



//算法三 編譯最大,但有考慮順序步驟,只適合單倍
uint8_t EC_Index;
uint8_t EC_Last;
uint8_t EC_Now;
int EC_Counter;
int EC_CountTemp;
void Encoder_Ini()
{
   EC_Last=P1 & 0x03;
   EC_Counter=0;
         EC_Index=0x40;
}
void Encoder_Run()
{
        uint8_t temp;
        EC_Now=P1 & 0x03;
        temp=EC_Now^EC_Last;
        EC_Last=EC_Now;        
        EC_Index>>=temp;
        if(EC_Now==0x03)  //注意是編碼器默認的電平
        {
           EC_Index=0x40;
        }
        if(EC_Index==2 || EC_Index==4)
        {
                EC_Counter+=(EC_Index-3);  //如要調整方向,請修改此處
                EC_Index=0x40;
        }
}

原理解析:
B對應P11 A對應P10
默認編碼器值為高電平,即A=1,B=1,
反轉分析:
第一步:A=1,B=1,EC_Last=0x03 , EC_Now=0x03  為什么會是0x03 , 因為P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x03=0,因此temp=0;
EC_Index>>=temp 即 EC_Index>>=0;此時EC_Index不變,還是0x40 二進制是0100 0000
而且,細心的網友會發現,這句程序:
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}
因此EC_Index最后還是等于0x40
第二步:A=1,B=0,EC_Last=0x03 , EC_Now=0x01  為什么會是0x01 , 因為P1 & 0x03=xxxxxx01 & 00000011=00000001=0x01
EC_Now^EC_Last=0x01^0x03=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此時EC_Index=0x10 二進制是0001 0000

第三步:A=0,B=0,EC_Last=0x01 , EC_Now=0x00  為什么會是0x00 , 因為P1 & 0x03=xxxxxx00 & 00000011=00000000=0x00
EC_Now^EC_Last=0x00^0x01=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此時EC_Index=0x0F 二進制是0000 1000

第四步:A=0,B=1,EC_Last=0x00 , EC_Now=0x02  為什么會是0x02 , 因為P1 & 0x03=xxxxxx10 & 00000011=00000010=0x02
EC_Now^EC_Last=0x02^0x00=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此時EC_Index=0x02 二進制是0000 0010

此時,EC_Index=0x02 符合條件更新計數的條件 EC_Index==0x02 或 EC_Index==0x04
(EC_Index-3)=2-3=-1
EC_Counter+=(EC_Index-3) ,即EC_Counter+= - 1 ,自動減1了
第五步:A=1,B=1,EC_Last=0x02 , EC_Now=0x03  為什么會是0x03 , 因為P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x02=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此時EC_Index=0x01 二進制是0000 0001
細心的網友會發現,這句程序,
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}因此EC_Index最后還是等于0x40;運行到此步后,會從第二步繼續循環;

正轉分析:
第一步:A=1,B=1,EC_Last=0x03 , EC_Now=0x03  為什么會是0x03 , 因為P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x03=0,因此temp=0;
EC_Index>>=temp 即 EC_Index>>=0;此時EC_Index不變,還是0x40 二進制是0100 0000
而且,細心的網友會發現,這句程序:
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}

因此EC_Index最后還是等于0x40
第二步:A=0,B=1,EC_Last=0x03 , EC_Now=0x02  為什么會是0x02 , 因為P1 & 0x03=xxxxxx10 & 00000011=00000010=0x02
EC_Now^EC_Last=0x02^0x03=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此時EC_Index=0x20 二進制是0010 0000

第三步:A=0,B=0,EC_Last=0x02 , EC_Now=0x00  為什么會是0x00 , 因為P1 & 0x03=xxxxxx00 & 00000011=00000000=0x00
EC_Now^EC_Last=0x00^0x02=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此時EC_Index=0x0F 二進制是0000 1000

第四步:A=1,B=0,EC_Last=0x00 , EC_Now=0x01  為什么會是0x01 , 因為P1 & 0x03=xxxxxx01 & 00000011=00000001=0x01
EC_Now^EC_Last=0x01^0x00=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此時EC_Index=0x04 二進制是0000 0100

此時,EC_Index=0x04 符合條件更新計數的條件 EC_Index==0x02 或 EC_Index==0x04
(EC_Index-3)=4-3=1
EC_Counter+=(EC_Index-3) ,即EC_Counter+=1 ,自動加1了第五步:A=1,B=1,EC_Last=0x01 , EC_Now=0x03  為什么會是0x03 , 因為P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x01=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此時EC_Index=0x01 二進制是0000 0001
細心的網友會發現,這句程序,
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}因此EC_Index最后還是等于0x40;運行到此步后,會從第二步繼續循環;
從上面的分析可以看出,算法是有按順序對每個步驟進行處理并關聯到了temp和EC_Index的值,從而決定了EC_Counter的值
這個算法的核心是:
反轉一格時,EC_Now^EC_Last的值是0,2,1,2, 1 的變化,第一步和第五步為默認狀態,EC_Index重置為0x40,移位不起作用,
因此實際反轉時,EC_Index右移了2+1+2=5次,最終等于2;
正轉一格時,EC_Now^EC_Last的值是0,1,2,1,  2 的變化,第一步和第五步為默認狀態,EC_Index重置為0x40,移位不起作用,
因此實際正轉時,EC_Index右移了1+2+1=4次,最終等于4;

然后用 EC_Index-3 巧妙的得到了正負1,實現自動正反轉加減;
現在可以解析EC_Index重置為0x40的意義:0x40二進制是0100 0000,右移位4或5次時能得到4和2的值,其他數值不行;


以上就是我原創的EC11編碼器基于運算解碼的算法,希望能給大家拋磚引玉。








評分

參與人數 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏41 分享淘帖 頂8 踩
回復

使用道具 舉報

沙發
ID:471574 發表于 2023-12-13 23:11 | 只看該作者
同時貼上lkc8210發表的算法:
//算法四: 編譯大小不錯,只適合單倍頻
uint8_t KeyA_Last;
uint8_t KeyB_Last;
uint8_t KeyA_Now;
uint8_t KeyB_Now;
int EC_Counter;

void Encoder_Ini()
{
    KeyA_Last = P10;
    KeyB_Last = P11;
}

void Encoder_Run()
{
        KeyA_Now=P10;
        KeyB_Now=P11;
        if(!KeyA_Now && KeyA_Last && KeyB_Now)
        {
                EC_Counter++;
  }
        KeyA_Last=KeyA_Now;
        if(!KeyB_Now && KeyB_Last && KeyA_Now)
        {
                EC_Counter--;
  }
        KeyB_Last=KeyB_Now;
}
回復

使用道具 舉報

板凳
ID:1064915 發表于 2023-12-14 08:28 | 只看該作者
好文章,需要認真學習
回復

使用道具 舉報

地板
ID:156220 發表于 2023-12-14 10:14 | 只看該作者
講解的蠻詳細的,謝謝樓主的分享
回復

使用道具 舉報

5#
ID:514317 發表于 2023-12-14 11:56 | 只看該作者
經過測試   樓主的程序運行穩定    算法精簡高效    感謝樓主
只是 (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)這段編譯報錯   只好拆成2段
我也貼上我常用的   也是很穩定


if (PinA != PinA_O)        //當A發生跳變時采集B當前的狀態,并將B與上一次的狀態進行對比。
        {                                   //若A 0->1 時,B 1->0 正轉;若A 1->0 時,B 0->1 正轉;
                                                                                //若A 0->1 時,B 0->1 反轉;若A 1->0 時,B 1->0 反轉
                if (PinA == 1)     //EC11_A和上一次狀態相比,為上升沿
                {
                if ((PinB_O == 1) && (PinB == 0))   //EC11_B和上一次狀態相比,為下降沿
                        encoder_data++;                         //正轉
                if ((PinB_O == 0) && (PinB == 1))   //EC11_B和上一次狀態相比,為上升沿               
                        encoder_data--;                        //反轉
                //>>>>>>>>>>>>>>>>下面為正轉一次再反轉或反轉一次再正轉處理<<<<<<<<<<<<<<<<//
                if ((PinB_O == PinB) && (PinB == 0))  //A上升沿時,采集的B不變且為0
                    encoder_data++;                                 //正轉
                if ((PinB_O == PinB) && (PinB == 1))  //A上升沿時,采集的B不變且為1
                        encoder_data--;                                //反轉
                }

                else                    //EC11_A和上一次狀態相比,為下降沿
                {
                if ((PinB_O == 1) && (PinB == 0))   //EC11_B和上一次狀態相比,為下降沿
                        encoder_data--;                        //反轉
                if ((PinB_O == 0) && (PinB == 1))   //EC11_B和上一次狀態相比,為上升沿
                        encoder_data++;                         //正轉
                //>>>>>>>>>>>>>>>>下面為正轉一次再反轉或反轉一次再正轉處理<<<<<<<<<<<<<<<<//
                if ((PinB_O == PinB) && (PinB == 0))  //A上升沿時,采集的B不變且為0
                    encoder_data--;                                //反轉
                if ((PinB_O == PinB) && (PinB == 1))  //A上升沿時,采集的B不變且為1   
                        encoder_data++;                                 //正轉
                }
                PinA_O = PinA;   //更新編碼器上一個狀態暫存變量
                PinB_O = PinB;   //更新編碼器上一個狀態暫存變量
回復

使用道具 舉報

6#
ID:471574 發表于 2023-12-14 13:08 | 只看該作者
lzzasd 發表于 2023-12-14 11:56
經過測試   樓主的程序運行穩定    算法精簡高效    感謝樓主
只是 (int)((KeyA_Last ^ KeyA_Now) - (KeyB ...

編譯什么提示?我是keil4 C51 編譯正常,會不會少了個括號標點之類的?
回復

使用道具 舉報

7#
ID:417804 發表于 2023-12-15 09:54 | 只看該作者
小白只能頂樓主
回復

使用道具 舉報

8#
ID:514317 發表于 2023-12-16 10:27 | 只看該作者
zyhlove813 發表于 2023-12-14 13:08
編譯什么提示?我是keil4 C51 編譯正常,會不會少了個括號標點之類的?

APP_EC11.C(59):C193: '-': BAD OPERAND TYPE
后段那個 減號   拆成2段就正常了
回復

使用道具 舉報

9#
ID:514317 發表于 2023-12-16 10:42 | 只看該作者
zyhlove813 發表于 2023-12-14 13:08
編譯什么提示?我是keil4 C51 編譯正常,會不會少了個括號標點之類的?

剛才看了下   是我定義的變量的問題    我的變量都是BIT 位類型的   編譯就出錯
樓主使用的是u8類型的   
回復

使用道具 舉報

10#
ID:537530 發表于 2023-12-24 19:28 | 只看該作者
樓主鉆研精神可嘉,學習了。
回復

使用道具 舉報

11#
ID:471574 發表于 2023-12-25 13:07 | 只看該作者
發表于 2023-12-24 19:28
樓主鉆研精神可嘉,學習了。

共同學習
回復

使用道具 舉報

12#
ID:604453 發表于 2023-12-25 18:09 | 只看該作者
樓主的算法還需要硬件消抖電路嗎
回復

使用道具 舉報

13#
ID:604453 發表于 2023-12-25 19:14 | 只看該作者
代碼精簡高效,向樓主學習了
回復

使用道具 舉報

14#
ID:471574 發表于 2023-12-25 21:04 | 只看該作者
lzuoxin 發表于 2023-12-25 18:09
樓主的算法還需要硬件消抖電路嗎

正常應該是要的,我是網購的模塊,帶電阻和電容濾波,不硬件濾波,你自己可以試下。
回復

使用道具 舉報

15#
ID:604453 發表于 2023-12-26 09:43 | 只看該作者
zyhlove813 發表于 2023-12-25 21:04
正常應該是要的,我是網購的模塊,帶電阻和電容濾波,不硬件濾波,你自己可以試下。

好的,我去試一下,謝謝!
回復

使用道具 舉報

16#
ID:983641 發表于 2023-12-31 21:35 | 只看該作者
講解得很詳細。UP厲害人。
回復

使用道具 舉報

17#
ID:471574 發表于 2024-1-16 18:04 | 只看該作者
youlinys 發表于 2023-12-31 21:35
講解得很詳細。UP厲害人。

通過不同的方法去實現目標,可能鍛煉自己的思維能力
回復

使用道具 舉報

18#
ID:471574 發表于 2024-7-10 13:28 | 只看該作者
這么特異的算法都沉底了
回復

使用道具 舉報

19#
ID:63692 發表于 2024-7-19 14:35 | 只看該作者

樓主鉆研精神可嘉,向你學習。
回復

使用道具 舉報

20#
ID:228467 發表于 2024-7-19 18:49 | 只看該作者
zyhlove813 發表于 2024-7-10 13:28
這么特異的算法都沉底了

沒有沉,都在學習中。感謝大佬分享的算法
回復

使用道具 舉報

21#
ID:471574 發表于 2024-10-5 16:37 | 只看該作者
今天玩了一下AI編程Cursor,對我的這個算法分析了下,說得很到位





回復

使用道具 舉報

22#
ID:433219 發表于 2024-10-7 16:32 | 只看該作者
編碼器,判斷誰先跳變,就當起始
回復

使用道具 舉報

23#
ID:479134 發表于 2024-11-6 12:25 | 只看該作者
講解的思路真的很清晰啊
回復

使用道具 舉報

24#
ID:98767 發表于 2024-11-10 21:39 | 只看該作者
看了up的視頻,特意搜了關鍵字找到了^_^
回復

使用道具 舉報

25#
ID:471574 發表于 2024-11-14 11:34 | 只看該作者
kkfy888 發表于 2024-11-10 21:39
看了up的視頻,特意搜了關鍵字找到了^_^

有心了
回復

使用道具 舉報

26#
ID:79034 發表于 2025-2-18 09:57 | 只看該作者
zyhlove813 發表于 2023-12-13 23:11
同時貼上lkc8210發表的算法:
//算法四: 編譯大小不錯,只適合單倍頻
uint8_t KeyA_Last;

請教一下樓主,這個怎么消抖的呢?
回復

使用道具 舉報

27#
ID:471574 發表于 2025-2-19 15:59 | 只看該作者
邰夏留 發表于 2025-2-18 09:57
請教一下樓主,這個怎么消抖的呢?

我用的是模塊,應該是加了電容消抖。軟件消抖這個不好處理,你可以測試下,不消抖有什么問題
回復

使用道具 舉報

28#
ID:30165 發表于 2025-2-20 10:54 | 只看該作者
我經常使用的程序。非常靈敏!定時器3毫秒以內都毫不拖泥帶水。
sbit EC11_A = P3^5;           //EC11 A端
sbit EC11_B = P3^3;           //EC11 B端
void EC11_Display()
{
   static bit EC11_Flag=0,Left_Flag=0,Right_Flag=0;

   if((EC11_A)&&(EC11_B))//兩個都是1,表示開始第一個脈沖
     {
       EC11_Flag =1 ;//標記為第一個信號收到,可以進行下一個信號
      }

    if(EC11_A!=EC11_B)//第二個信號
     {
       Left_Flag = EC11_A ; //記錄AB的信號狀態
       Right_Flag = EC11_B ;
      }

    if(EC11_Flag)
     {
       if((EC11_A==0)&&(EC11_B==0))// 第三個信號,處理第二個信號的值
         {
           if(Right_Flag)//右轉
          {
                //自己程序      
          }
     else if(Left_Flag) //左轉
         {                             
             //自己程序
          }
         EC11_Flag = 0; //把標志位清零,等待下一個周期
       }
    }       
}
回復

使用道具 舉報

29#
ID:21740 發表于 2025-2-21 16:54 | 只看該作者
zhang32568 發表于 2025-2-20 10:54
我經常使用的程序。非常靈敏!定時器3毫秒以內都毫不拖泥帶水。
sbit EC11_A = P3^5;           //EC11 A ...

剛試了代碼非常穩定可靠!謝謝分享!!!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久www| 久久一二| 免费精品 | 久久国产欧美日韩精品 | 免费一级片| 亚洲三级免费看 | 久久久久电影 | 一区二区在线免费观看 | 成人精品一区二区三区中文字幕 | 成人欧美一区二区三区 | 黑人性hd| 亚洲第1页 | 亚洲高清久久 | 天天干狠狠干 | 91精品国产一区二区三区 | 免费黄网站在线观看 | 99免费在线观看视频 | 欧美一级片在线观看 | 国产成人网 | 亚洲狠狠爱 | 精品视频在线一区 | 韩三级在线观看 | 瑟瑟激情| 国产综合在线视频 | 久久成人国产 | 久久久久久亚洲 | 国产一区二区激情视频 | 国产在视频一区二区三区吞精 | 在线一区观看 | 麻豆国产一区二区三区四区 | 嫩草视频免费 | 国产综合精品一区二区三区 | 久久久久国产精品免费免费搜索 | 国产精品久久久久9999鸭 | 午夜视频在线免费观看 | 欧洲一区二区视频 | 国产午夜精品一区二区三区 | 日韩综合一区 | 九九视频网 | 日韩欧美国产综合 | 三级在线观看 |