旋轉編碼器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:反轉;
}