这个我实在网上找了好久找了一个可用的程序,大部分,你搜索编码器程序出来的都是电机的相关程序,而我要的是旋钮式的,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里我又添加了另外四个独立按键的扫描,按键和编码器都可以正常运行,有个问题就是每次按键时,数码管的会闪一下,就好像按键时停止了一下数码管的显示,很明显,肉眼能观察到。
主要的部分程序:
// 初始化左右旋转编码器的状态
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);
}