這個我實在網上找了好久找了一個可用的程序,大部分,你搜索編碼器程序出來的都是電機的相關程序,而我要的是旋鈕式的,PEC11-4020F-S0018型號的編碼器。
這個代碼寫得挺完善的,就是沒有寫主函數,因此調用問題上,還是費了好些神才弄出來,關鍵它里面的一些定義,我很久沒有些程序,都不清楚了,如:
typedef struct tagspin
{
RotateStatus rotatestatus; // 旋轉狀態
KeyStatus keystatus; // 按鍵狀態
}struspin;
我知道struct為結構體,但是typedef就真的忘了,百度一下,就清楚了。在主函數里只需
struspin left_spin;
struspin right_spin;
在調用函數void Init_Spin_Status(struspin *left_spin, struspin *right_spin)和void Read_Spin(struspin *left_spin, struspin *right_spin)時,就又忘了*left_spin這是指針的,因此:
Init_Spin_Status( &left_spin , &right_spin ); 要添加&
Read_Spin(&left_spin, &right_spin);
修改相關配置,在主函數加幾句調用,便可以運行了,不過至今還有幾個問題:
1、目前程序的執行是旋轉編碼器兩次才有加1或減1;
2、PEC11-4020F-S0018碼編器,一圈有30個定位,實物自己轉出來數的。資料里0018 = 18 Pulses per 360 ° Rotation 我的理解是一圈18個脈沖,一圈有30個定位18個脈沖,那一個定位應該有幾個脈沖呢?再研究下程序,怎么會轉兩個定位加1操作一次;
3、我用的循環掃描的方式,編碼器有按鍵功能,當只有掃描編碼器不顯示數碼管時,按鍵的程序是要亮燈,可是實際就是閃一下沒有,不過當我在主程序里加上數碼管的顯示,按鍵的燈就可以一直亮着了;
4、在主函數的while里我又添加了另外四個獨立按鍵的掃描,按鍵和編碼器都可以正常運行,有個問題就是每次按鍵時,數碼管的會閃一下,就好像按鍵時停止了一下數碼管的顯示,很明顯,肉眼能觀察到。
上面幾個問題的部分分析:(2015.11.21)
1、這個是程序的問題,在每次出來的波用三個點去判斷即可;
2、當時的資料和實物不符,所有有這個問題,應該是每次旋轉一個定位就出一個波,A相和B想分別一個波;
主要的部分程序:
// 初始化左右旋轉編碼器的狀態
void Init_Spin_Status(struspin *left_spin, struspin *right_spin)
{
l eft_spin->rotatestatus = SPIN_NO_ROTATE;
left_spin->keystatus = KEY_NO_PRESSED;
right_spin->rotatestatus = SPIN_NO_ROTATE;
right_spin->keystatus = KEY_NO_PRESSED;
}
////////////////////////////////////////////////////////////
// 讀取 2 旋轉編碼器的狀態
static LEVEL last_leftspinkey_level= H, last_rightspinkey_level= H; // 保存的上一次按鍵的電平情況
static SpinABstatus last_leftspinABst=SPIN_AB_ST3, last_rightspinABst=SPIN_AB_ST3; // 保存的上一次AB引腳的電平情況
void Read_Spin(struspin *left_spin, struspin *right_spin)
{
LEVEL now_leftspinkey_level, now_rightspinkey_level;
LEVEL now_leftspinA_level, now_leftspinB_level;
LEVEL now_rightspinA_level, now_rightspinB_level;
SpinABstatus now_leftspinABst, now_rightspinABst;
// 先讀取旋轉編碼器的各引腳的電平值
if( READ_SPIN_L_KEY() ) { now_leftspinkey_level = H; } // 讀取左側旋轉編碼器的按鍵電平值
else { now_leftspinkey_level = L; }
if( READ_SPIN_R_KEY() ) { now_rightspinkey_level = H; } // 讀取右側旋轉編碼器的按鍵電平值
else { now_rightspinkey_level = L; }
if( READ_SPIN_L_A() ) { now_leftspinA_level = H; } // 讀取左側旋轉編碼器的 A 信號電平值
else { now_leftspinA_level = L; }
if( READ_SPIN_L_B() ) { now_leftspinB_level = H; } // 讀取左側旋轉編碼器的 B 信號電平值
else { now_leftspinB_level = L; }
if( READ_SPIN_R_A() ) { now_rightspinA_level = H; } // 讀取右側旋轉編碼器的 A 信號電平值
else { now_rightspinA_level = L; }
if( READ_SPIN_R_B() ) { now_rightspinB_level = H; } // 讀取右側旋轉編碼器的 B 信號電平值
else { now_rightspinB_level = L; }
// 根據 左側旋轉編碼器的按鍵 前后 兩次的電平值, 確定按鍵狀態
if( (last_leftspinkey_level == H) && (now_leftspinkey_level == L) ) { left_spin->keystatus = KEY_JUST_PRESSED; }
else if((last_leftspinkey_level == H) && (now_leftspinkey_level == H) ) { left_spin->keystatus = KEY_NO_PRESSED; }
else if((last_leftspinkey_level == L) && (now_leftspinkey_level == H) ) { left_spin->keystatus = KEY_JUST_POPUP; }
else { left_spin->keystatus = KEY_ALREADY_PRESSED; }
// 根據 右側旋轉編碼器的按鍵 前后 兩次的電平值, 確定按鍵狀態
if( (last_rightspinkey_level == H) && (now_rightspinkey_level == L) ) { right_spin->keystatus = KEY_JUST_PRESSED; }
else if((last_rightspinkey_level == H) && (now_rightspinkey_level == H) ) { right_spin->keystatus = KEY_NO_PRESSED; }
else if((last_rightspinkey_level == L) && (now_rightspinkey_level == H) ) { right_spin->keystatus = KEY_JUST_POPUP; }
else { right_spin->keystatus = KEY_ALREADY_PRESSED; }
// 根據 左側旋轉編碼器的 A B 的電平值, 確定 AB 狀態
if( (now_leftspinA_level == H) && (now_leftspinB_level == H) ) { now_leftspinABst = SPIN_AB_ST3; } // A=1 B=1;
else if((now_leftspinA_level == H) && (now_leftspinB_level == L) ) { now_leftspinABst = SPIN_AB_ST2; } // A=1 B=0;
else if((now_leftspinA_level == L) && (now_leftspinB_level == L) ) { now_leftspinABst = SPIN_AB_ST0; } // A=0 B=0;
else { now_leftspinABst = SPIN_AB_ST1; } // A=0 B=1;
// 根據 右側旋轉編碼器的 A B 的電平值, 確定 AB 狀態
if( (now_rightspinA_level == H) && (now_rightspinB_level == H) ) { now_rightspinABst = SPIN_AB_ST3; } // A=1 B=1;
else if((now_rightspinA_level == H) && (now_rightspinB_level == L) ) { now_rightspinABst = SPIN_AB_ST2; } // A=1 B=0;
else if((now_rightspinA_level == L) && (now_rightspinB_level == L) ) { now_rightspinABst = SPIN_AB_ST0; } // A=0 B=0;
else { now_rightspinABst = SPIN_AB_ST1; } // A=0 B=1;
// 再根據 左側旋轉編碼器 前后兩次 AB信號線的狀態, 確定是左旋還是右旋
if( (last_leftspinABst == SPIN_AB_ST3) && (now_leftspinABst == SPIN_AB_ST2)){ left_spin->rotatestatus = SPIN_UNTICLOCKWISE; }
else if ((last_leftspinABst == SPIN_AB_ST3) && (now_leftspinABst == SPIN_AB_ST1)){ left_spin->rotatestatus = SPIN_CLOCKWISE; }
else { left_spin->rotatestatus = SPIN_NO_ROTATE; }
// 再根據 右側旋轉編碼器 前后兩次 AB信號線的狀態, 確定是左旋還是右旋
if( (last_rightspinABst== SPIN_AB_ST3) && (now_rightspinABst== SPIN_AB_ST2)){ right_spin->rotatestatus = SPIN_UNTICLOCKWISE;}
else if ((last_rightspinABst== SPIN_AB_ST3) && (now_rightspinABst== SPIN_AB_ST1)){ right_spin->rotatestatus = SPIN_CLOCKWISE; }
else { right_spin->rotatestatus = SPIN_NO_ROTATE; }
last_leftspinkey_level = now_leftspinkey_level; // 保存當前狀態,作為下次狀態的依據
last_rightspinkey_level = now_rightspinkey_level;
last_leftspinABst = now_leftspinABst;
last_rightspinABst = now_rightspinABst;
}
// 右面旋轉編碼器,用戶自己的代碼
void Process_Right_Spin( struspin *rightspin)
{
if(rightspin->keystatus == KEY_JUST_PRESSED) // 旋轉編碼器的按鍵剛按下的處理程序,用戶自己填入
{
LED5=!LED5;
}
else if(rightspin->rotatestatus == SPIN_CLOCKWISE) // 旋轉編碼器順時針旋轉的處理程序,用戶自己填入
{
right_NUM++;
}
else if(rightspin->rotatestatus == SPIN_UNTICLOCKWISE) // 旋轉編碼器反時針旋轉的處理程序,用戶自己填入
{
right_NUM--;
}
}
//////////////////////////////////////////////////////
/////// 左面的旋轉編碼器 ///////////////
//#define RCC_LEFT_SPIN RCC_APB2Periph_GPIOC // 左面的旋轉編碼器使用的GPIOE時鍾
//#define GPIO_SPIN_L_PORT GPIOC // 左面的旋轉編碼器驅動引腳所在的端口
#define SPIN_L_KEY_PIN GPIO_Pin_9 // 左面的旋轉編碼器 按鍵 引腳號
#define pinSPINleftKEY PIN9
#define SPIN_L_A_PIN GPIO_Pin_7 // 左面的旋轉編碼器 A 引腳號
#define pinSPINleftA PIN7
#define SPIN_L_B_PIN GPIO_Pin_8 // 左面的旋轉編碼器 B 引腳號
#define pinSPINleftB PIN8
#define READ_SPIN_L_KEY() PCin(pinSPINleftKEY) // PC9
#define READ_SPIN_L_A() PCin(pinSPINleftA) // PC7 讀入 A 引腳的電平
#define READ_SPIN_L_B() PCin(pinSPINleftB) // PC8 讀入 B 引腳的電平
///////////////////////////////////////////////////
typedef enum
{
KEY_NO_PRESSED = 0,
KEY_JUST_PRESSED ,
KEY_ALREADY_PRESSED ,
KEY_JUST_POPUP ,
}KeyStatus;
typedef enum
{
L = 0, // 低電平
H , // 高電平
}LEVEL;
typedef enum
{
SPIN_NO_ROTATE = 0, // 無旋轉
SPIN_CLOCKWISE , // 順時針旋轉
SPIN_UNTICLOCKWISE , // 反時針旋轉
}RotateStatus;
typedef struct tagspin
{
RotateStatus rotatestatus; // 旋轉狀態
KeyStatus keystatus; // 按鍵狀態
}struspin;
typedef enum
{
SPIN_AB_ST0 = 0, // A=0 B=0;
SPIN_AB_ST1 , // A=0 B=1;
SPIN_AB_ST2 , // A=1 B=0;
SPIN_AB_ST3 , // A=1 B=1;
}SpinABstatus; // 旋轉編碼器信號線 A B 的電平
Init_Spin_Status( &left_spin , &right_spin );
left_NUM=0;
right_NUM=0;
LED5=0;
while(1)
{
Read_Spin(&left_spin, &right_spin);
Process_LEFT_Spin(&left_spin);
Process_Right_Spin( &right_spin);
display(0,left_NUM);
display(1,right_NUM);
}