旋轉編碼器EC11驅動

旋轉編碼器EC11驅動

/*-------->>>>>>>>--------注意事項:EC11旋轉編碼器的掃描時間間隔控制在1~4ms之間,
否則5ms及以上的掃描時間在快速旋轉時可能會誤判旋轉方向--------<<<<<<<<--------*/
//*******************************************************************/
//功能:初始化EC11旋轉編碼器相關參數
//形參:EC11旋轉編碼器的類型-->>  unsigned char Set_EC11_TYPE  <<--  :0----一定位對應一脈衝;1(或非0)----兩定位對應一脈衝。
//返回:無
//詳解:對EC11旋轉編碼器的連接IO口做IO口模式設置。以及將相關的變量進行初始化
//*******************************************************************/
void Encoder_EC11_Init(unsigned char Set_EC11_TYPE)
{
    EC11_A_Now = 1;
    EC11_B_Now = 1;
    EC11_Key = 1;

    //EC11類型選擇:0-一定位一脈衝;1-兩定位一脈衝
    if(Set_EC11_TYPE == 0)
    {
        EC11_Type = 0;
    }
    else
    {
        EC11_Type = 1;
    }

    //避免上電時EC11旋鈕位置不確定導致一次動作誤判
    EC11_A_Last = EC11_A_Now;   
    EC11_B_Last = EC11_B_Now;

    //--------清除按鍵計數器和標誌位--------//
    EC11_KEY_COUNT = 0;                     //EC11按鍵動作計數器
    EC11_KEY_DoubleClick_Count = 0;         //EC11按鍵雙擊動作計數器
    FLAG_EC11_KEY_ShotClick = 0;            //EC11按鍵短按動作標誌
    FLAG_EC11_KEY_LongClick = 0;            //EC11按鍵長按動作標誌
    FLAG_EC11_KEY_DoubleClick = 0;          //EC11按鍵雙擊動作標誌
}



//*******************************************************************/
//功能:掃描EC11旋轉編碼器的動作並將參數返回給動作分析函數使用
//形參:EC11旋轉編碼器的類型-->>  unsigned char Set_EC11_TYPE  <<--  :0----一定位對應一脈衝;1(或非0)----兩定位對應一脈衝
//返回:EC11旋轉編碼器的掃描結果-->>  char ScanResult  -->>  0:無動作;1:正轉; -1:反轉;2:只按下按鍵;
//                                                       3:按着按鍵正轉;-3:按着按鍵反轉
//詳解:只掃描EC11旋轉編碼器有沒有動作,不關心是第幾次按下按鍵或長按或雙擊。
//返回值直接作爲形參傳給 [ void Encoder_EC11_Analyze(char EC11_Value); ] 函數使用
//*******************************************************************/
char Encoder_EC11_Scan()
{
//以下儲存A、B上一次值的變量聲明爲靜態全局變量,方便對EC11對應的IO口做初始化
//  static char EC11_A_Last = 0;
//  static char EC11_B_Last = 0;
    char ScanResult = 0;    //返回編碼器掃描結果,用於分析編碼器的動作
                            //返回值的取值:   0:無動作;      1:正轉;           -1:反轉;  
                            //                  2:只按下按鍵;    3:按着按鍵正轉;   -3:按着按鍵反轉

    
    EC11_A_Now = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12);
    EC11_B_Now = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13);
    EC11_Key = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14);
    
                            //======================================================//
    if(EC11_Type == 0)      //================一定位對應一脈衝的EC11================//
    {                       //======================================================//
        if(EC11_A_Now != EC11_A_Last)   //以A爲時鐘,B爲數據。正轉時AB反相,反轉時AB同相
        {
            if(EC11_A_Now == 0)
            {
                if(EC11_B_Now ==1)      //只需要採集A的上升沿或下降沿的任意一個狀態,若A下降沿時B爲1,正轉                    
                    ScanResult = 1;     //正轉

                else                    //反轉
                    ScanResult = -1;
            }
            EC11_A_Last = EC11_A_Now;   //更新編碼器上一個狀態暫存變量
            EC11_B_Last = EC11_B_Now;   //更新編碼器上一個狀態暫存變量
        }
    }   
                            //======================================================//
    else                    //================兩定位對應一脈衝的EC11================//
    {                       //======================================================//
        if(EC11_A_Now !=EC11_A_Last)        //當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(EC11_A_Now == 1)     //EC11_A和上一次狀態相比,爲上升沿
            {
                if((EC11_B_Last == 1)&&(EC11_B_Now == 0))   //EC11_B和上一次狀態相比,爲下降沿
                    ScanResult = 1;                         //正轉

                if((EC11_B_Last == 0)&&(EC11_B_Now == 1))   //EC11_B和上一次狀態相比,爲上升沿               
                    ScanResult = -1;                        //反轉

                //>>>>>>>>>>>>>>>>下面爲正轉一次再反轉或反轉一次再正轉處理<<<<<<<<<<<<<<<<//
                if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 0))  //A上升沿時,採集的B不變且爲0
                    ScanResult = 1;                                 //正轉

                if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 1))  //A上升沿時,採集的B不變且爲1
                    ScanResult = -1;                                //反轉
            }

            else                    //EC11_A和上一次狀態相比,爲下降沿
            {
                if((EC11_B_Last == 1)&&(EC11_B_Now == 0))   //EC11_B和上一次狀態相比,爲下降沿
                    ScanResult = -1;                        //反轉

                if((EC11_B_Last == 0)&&(EC11_B_Now == 1))   //EC11_B和上一次狀態相比,爲上升沿
                    ScanResult = 1;                         //正轉

                //>>>>>>>>>>>>>>>>下面爲正轉一次再反轉或反轉一次再正轉處理<<<<<<<<<<<<<<<<//
                if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 0))  //A上升沿時,採集的B不變且爲0
                    ScanResult = -1;                                //反轉

                if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 1))  //A上升沿時,採集的B不變且爲1   
                    ScanResult = 1;                                 //正轉

            }               
            EC11_A_Last = EC11_A_Now;   //更新編碼器上一個狀態暫存變量
            EC11_B_Last = EC11_B_Now;   //更新編碼器上一個狀態暫存變量
        }
    }                                                                       

    if(EC11_Key == 0)   //如果EC11的按鍵按下,並且沒有EC11沒有轉動,
    {
        if(EC11_KEY_COUNT<10000)    //打開按鍵按下時間定時器
            EC11_KEY_COUNT++;
        if(EC11_KEY_COUNT == KEY_COUNT_DESHAKING)   //按下按鍵時間到達消抖時間時
        {                                           //置位短按按鍵標誌
            FLAG_EC11_KEY_ShotClick = 1;
        }
        if((EC11_KEY_DoubleClick_Count > 0)&&(EC11_KEY_DoubleClick_Count <= KEY_COUNT_DUALCLICKTIME))   //鬆開按鍵後,又在定時器在雙擊時間內按下按鍵
        {                                                                                               //置位雙擊按鍵標誌
            FLAG_EC11_KEY_DoubleClick = 1;
        }

        if(EC11_KEY_COUNT == KEY_COUNT_LONGTIME)    //按下按鍵時間到達長按時間
        {                                           //置位長按按鍵標誌並復位短按按鍵標誌
            FLAG_EC11_KEY_LongClick = 1;
            FLAG_EC11_KEY_ShotClick = 0;
        }
    }
    else
    {
        if(EC11_KEY_COUNT < KEY_COUNT_DESHAKING)    //沒到消抖時長就鬆開按鍵,復位所有定時器和按鍵標誌
        {
            EC11_KEY_COUNT = 0;
            FLAG_EC11_KEY_ShotClick = 0;
            FLAG_EC11_KEY_LongClick = 0;
            FLAG_EC11_KEY_DoubleClick = 0;
            EC11_KEY_DoubleClick_Count = 0;
        }
        else
        {
            
            if(FLAG_EC11_KEY_ShotClick == 1)        //短按按鍵定時有效期間
            {
                if((FLAG_EC11_KEY_DoubleClick == 0)&&(EC11_KEY_DoubleClick_Count >= 0)) 
                    EC11_KEY_DoubleClick_Count++;
                if((FLAG_EC11_KEY_DoubleClick == 1)&&(EC11_KEY_DoubleClick_Count <= KEY_COUNT_DUALCLICKTIME))   //如果在規定雙擊時間內再次按下按鍵
                {                                                                                               //認爲按鍵是雙擊動作
                    FLAG_EC11_KEY_DoubleClick = 2;
                }   

                if((FLAG_EC11_KEY_DoubleClick == 0)&&(EC11_KEY_DoubleClick_Count > KEY_COUNT_DUALCLICKTIME))    //如果沒有在規定雙擊時間內再次按下按鍵
                    FLAG_EC11_KEY_ShotClick = 0;                                                                //認爲按鍵是單擊動作
            }

            if(FLAG_EC11_KEY_LongClick == 1)        //檢測到長按按鍵鬆開
                FLAG_EC11_KEY_LongClick = 0;
        }
    }

    //>>>>>>>>>>>>>>>>編碼器按鍵分析處理程序<<<<<<<<<<<<<<<<//
    if(EC11_KEY_COUNT > KEY_COUNT_DESHAKING)    //短按按鍵延時到了時間
    {

        //短按按鍵動作結束代碼
        if((FLAG_EC11_KEY_ShotClick == 0)&&(EC11_KEY_DoubleClick_Count > KEY_COUNT_DUALCLICKTIME)&&(EC11_KEY_COUNT < KEY_COUNT_LONGTIME))   //短按按鍵動作結束代碼
        {
            //--------短按按鍵動作結束代碼--------//
            EC11_NUM_SW++;
            if(EC11_NUM_SW >= 4)
                EC11_NUM_SW = 1;
            ScanResult = 2;
            //--------清除標誌位--------//
            EC11_KEY_COUNT = 0;
            EC11_KEY_DoubleClick_Count = 0;
            FLAG_EC11_KEY_DoubleClick = 0;
        }

        //雙擊按鍵動作結束代碼
        if((FLAG_EC11_KEY_DoubleClick == 2)&&(EC11_KEY_DoubleClick_Count > 0)&&(EC11_KEY_DoubleClick_Count <= KEY_COUNT_DUALCLICKTIME)) //雙擊按鍵動作結束代碼
        {
            //--------雙擊按鍵動作結束代碼--------//
            if(EC11_NUM_SW == 5)
                EC11_NUM_SW = 0;
            if(EC11_NUM_SW == 4)
                EC11_NUM_SW = 5;

            if(EC11_NUM_SW <4)
            {
                EC11_NUM_SW = 4;
            }
            ScanResult = 3;
            //--------清除標誌位--------//
            EC11_KEY_COUNT = 0;
            EC11_KEY_DoubleClick_Count = 0;
            FLAG_EC11_KEY_ShotClick = 0;
            FLAG_EC11_KEY_DoubleClick = 0;
            
        }

        //連續長按按鍵按下代碼
        if((FLAG_EC11_KEY_LongClick == 1)&&(EC11_KEY_COUNT >= KEY_COUNT_LONGTIME))  //連續長按按鍵按下代碼
        {
            TMP_Value ++;
            if(TMP_Value % KEY_LONG_REPEAT_TIME == 0)
            {
                TMP_Value = 0;
                //-------連續長按按鍵按下代碼--------//
                ScanResult = 4;
            }
        }

        //長按按鍵動作結束代碼
        if((FLAG_EC11_KEY_LongClick == 0)&&(EC11_KEY_COUNT >= KEY_COUNT_LONGTIME))  //長按按鍵動作結束代碼
        {                                                                           
            //--------長按按鍵按下動作結束代碼--------//
            EC11_NUM_SW = 0;
            ScanResult = 5;
            //--------清除標誌位--------//
            EC11_KEY_COUNT = 0;
        }
    }
    return ScanResult;      //返回值的取值:   0:無動作;      1:正轉;           -1:反轉;
}   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章