STM32 学习总结4 --- 编码器 旋钮式 增量编码器

  这个我实在网上找了好久找了一个可用的程序,大部分,你搜索编码器程序出来的都是电机的相关程序,而我要的是旋钮式的,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); 
}

转载于:https://www.cnblogs.com/vowping151105/p/4977760.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值