AB正交解码

芯片内部正交解码原理及实现

1.正交方波信号常见于电机的测速编码器上,编码器输出两路信号PHA和PHB,用两者的相位差(90或-90)来表示电机的正反转。
2.对于正交信号的方向解码可以使用D触发器,一相作为D触发器的CLK信号,一相作为D触发器的DATA信号,当CLK超前DATA  90度时,D触发器稳定输出高电平,当CLK延迟DATA 90度时,D触发器稳定输出低电平,以此可以对方向解码。但是由于正交信号毛刺较多,特别是输入CLK的信号出现毛刺时候,很容易造成方向信号解码出错,所以用D触发器解码是不够稳定的。
3.对正交信号的速度解码只需将AB相中的一相或者两相异或(频率加倍)输入一个脉冲累加单元,配合定时器即可解出速度信息。
4.由于正交信号在控制领域非常常见,所以一些稍微高端的芯片内部直接集成了AB正交解码模块。
5.芯片内部的正交解码原理如下:当两相信号有一相发生跳变时,如果另一相为高电平,则计数器递增,如果另一相为低电平则计数器递减,如果计数器发生溢出,则对应的溢出标志位和溢出方向标志位会相应置位,通过读取这两个标志寄存器的值可以判断计数器的计数方向,配合计数器的值和计时器就可以计算出速度。
下面以飞思卡尔公司的K60芯片为例介绍正交解码的配置和实现。
使用LPLD的K60底层库:
(1)初始化FTM的正交解码功能,注意芯片手册上那些通道具有AB正交解码功能
//编码器初始化程序
void Encoder_Init(void)
{
  FTM_InitTypeDef ftm_init_struct;
  //配置正交解码功能参数,两个通道分别测两个轮子
  ftm_init_struct.FTM_Ftmx = FTM1;              //只有FTM1和FTM2有正交解码功能
  ftm_init_struct.FTM_Mode = FTM_MODE_QD;       //正交解码功能
  ftm_init_struct.FTM_QdMode = QD_MODE_PHAB;//QD_MODE_CNTDIR;    //AB相输入模式或者方向输入模式 QD_MODE_CNTDIR

  //初始化FTM
  LPLD_FTM_Init(ftm_init_struct);
  
  //使能AB相输入通道
  //PTB0引脚接A相输入、PTB1引脚接B相输入
  LPLD_FTM_QD_Enable(FTM1, PTB0, PTB1);
  LPLD_FTM_ClearCounter(FTM1);
  ftm_init_struct.FTM_Ftmx = FTM2;              //只有FTM1和FTM2有正交解码功能
  ftm_init_struct.FTM_Mode = FTM_MODE_QD;       //正交解码功能
  ftm_init_struct.FTM_QdMode = QD_MODE_PHAB;//QD_MODE_CNTDIR;    //AB相输入模式或者方向输入模式 QD_MODE_CNTDIR
  //初始化FTM
  LPLD_FTM_Init(ftm_init_struct);
  
  //使能AB相输入通道
  //PTB18引脚接A相输入、PTB19引脚接B相输入
  LPLD_FTM_QD_Enable(FTM2, PTB18, PTB19);
  LPLD_FTM_ClearCounter(FTM2);
}

(2)读取方向信号
此处通过判断计数器溢出标志位和溢出方向标志位来判断方向
//获得当前的方向
void GetCurrentDir(void)
{
  if(RIGHT_FTM_CHANNEL->SC & FTM_SC_TOF_MASK)//判断是否溢出
  {
    if(!(RIGHT_FTM_CHANNEL->QDCTRL & FTM_QDCTRL_TOFDIR_MASK))//判断溢出方向
    {
      g_dirOfRight = DIR_BACKWARD;
    }
    else
    {
      g_dirOfRight = DIR_FORWARD;
    }
    RIGHT_FTM_CHANNEL->SC &= ~0x01<QDCTRL & FTM_QDCTRL_TOFDIR_MASK)//判断是否溢出
  {
    if(!(LEFT_FTM_CHANNEL->QDCTRL & FTM_QDCTRL_TOFDIR_MASK))//判断溢出方向
    {
      g_dirOfLeft = DIR_BACKWARD;
    }
    else
    {
      g_dirOfLeft = DIR_FORWARD;
    }
    LEFT_FTM_CHANNEL->SC &= ~0x01<
(3)速度更新
该该函数需要放在定时器中断中,配合定时器就可以计算出速度
/更新当前速度
void UpdateCurrentSpeed(void)
{
  static uint16 counterTemp;
  GetCurrentDir();
	//左轮速度更新
    counterTemp=(LPLD_FTM_GetCounter(LEFT_FTM_CHANNEL));
    counterTemp=(g_dirOfLeft == DIR_FORWARD?counterTemp:0xFFFF-counterTemp);
    //printf("%d\n",counterTemp);
    g_carInfo.leftSpeed=(counterTemp)*ENCODER_SPEED_K/SPEED_PERIOD/2;//因为经过了异或门,所以除以2
    g_carInfo.leftSpeed = (g_dirOfLeft == DIR_FORWARD?g_carInfo.leftSpeed:-g_carInfo.leftSpeed);
	//右轮速度更新
   counterTemp=(LPLD_FTM_GetCounter(RIGHT_FTM_CHANNEL));
   counterTemp=(g_dirOfRight == DIR_FORWARD?counterTemp:0xFFFF-counterTemp);
   //printf("%d\n",counterTemp);
   g_carInfo.rightSpeed=(counterTemp)*ENCODER_SPEED_K/SPEED_PERIOD/2;
   g_carInfo.rightSpeed = g_dirOfRight == DIR_FORWARD?g_carInfo.rightSpeed:(-g_carInfo.rightSpeed);
//计数器清空
    LPLD_FTM_ClearCounter(FTM1);
    LPLD_FTM_ClearCounter(FTM2);
}

以上仅仅是个人对正交解码的一点点认识,还请大家批评指正!

你可能感兴趣的:(嵌入式,AB正交解码,编码器,K60,FTM)