×
单片机 > 单片机程序设计 > 详情

STM32正交编码器驱动,引入(突变)带进位的位置环和速度环

发布时间:2020-05-21 发布时间:
|

STM32正交编码器驱动,引入(突变)带进位的位置环和速度环 http://bbs.elecfans.com/jishu_484159_1_1.html (出处: 中国电子技术论坛)



#include "stm32f10x.h"
#include "stm32f10x_encoder.h"
#include "sys.h"
#include "usart.h"
#include "led.h"




#define COUNTER_RESET   (u16)0
#define ICx_FILTER      (u8) 0 // 6 670nsec 

#define TIMx_PRE_EMPTION_PRIORITY 1
#define TIMx_SUB_PRIORITY 0

//#define MAX_COUNT ENCODER_TIM_PERIOD/2





volatile s16 Right_hEncoder_Timer_Overflow;                 //编码器计数值溢出标志
volatile s16 Right_hEncoder_Timer_Overflow_High;        //编码器计数值溢出标志高位
volatile s16 Right_hRot_Speed;                                                //当前的速度
volatile s16 Right_hRot_Acceleration;                                //当前的加速度

s32 Right_CurrentCount = 0;                                                        //编码器当前的总计数值
s32 Right_CurrentCount_high = 0;                                        //编码器当前的总计数值高位  计算公式,注意结果可能超过32位的表示范围Left_CurrentCount_high*S32_MAX+Left_CurrentCount

volatile s16 Left_hEncoder_Timer_Overflow; 
volatile s16 Left_hEncoder_Timer_Overflow_High;
volatile s16 Left_hRot_Speed;
volatile s16 Left_hRot_Acceleration;

s32 Left_CurrentCount = 0;
s32 Left_CurrentCount_high = 0;

void ENC_Right_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef TIM_ICInitStructure;
  
    
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
  GPIO_StructInit(&GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;        //A7接靠近红色的编码器输入一端
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  
  TIM_DeInit(ENCODER_Right_TIMER);
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  // No prescaling 
  TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1;  
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(ENCODER_Right_TIMER, &TIM_TimeBaseStructure);
//TIMx_SMCR 寄存器中的 SMS=011 = TIM_EncoderMode_TI12;
  TIM_EncoderInterfaceConfig(ENCODER_Right_TIMER, TIM_EncoderMode_TI12, 
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); //ICx 不反相输入捕获在上升沿 
  TIM_ICStructInit(&TIM_ICInitStructure);         //TIM_Channel_1 TIM_ICPSC_DIV1 TIM_ICPolarity_Rising
  TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;        //输入滤波 0110:采样频率fSAMPLING=fDTS/4, N=6
  TIM_ICInit(ENCODER_Right_TIMER, &TIM_ICInitStructure);
  
// Clear all pending interrupts
  TIM_ClearFlag(ENCODER_Right_TIMER, TIM_FLAG_Update);
  TIM_ITConfig(ENCODER_Right_TIMER, TIM_IT_Update, ENABLE);
  //Reset counter
  ENCODER_Right_TIMER->CNT = COUNTER_RESET;
  

  
  TIM_Cmd(ENCODER_Right_TIMER, ENABLE);  
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        Right_hEncoder_Timer_Overflow = 0;
        Right_hEncoder_Timer_Overflow_High = 0;
        Right_hRot_Speed = 0;
        Right_ENC_Get_Electrical_Angle(); //第一次不要这个数据!!lastCount
}


void ENC_Left_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef TIM_ICInitStructure;
  
    
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
  GPIO_StructInit(&GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;        //A7接靠近红色的编码器输入一端
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY+1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  
  TIM_DeInit(ENCODER_Left_TIMER);
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  // No prescaling 
  TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1;  
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(ENCODER_Left_TIMER, &TIM_TimeBaseStructure);
//TIMx_SMCR 寄存器中的 SMS=011 = TIM_EncoderMode_TI12;
  TIM_EncoderInterfaceConfig(ENCODER_Left_TIMER, TIM_EncoderMode_TI12, 
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); //ICx 不反相输入捕获在上升沿 
  TIM_ICStructInit(&TIM_ICInitStructure);         //TIM_Channel_1 TIM_ICPSC_DIV1 TIM_ICPolarity_Rising
  TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;        //输入滤波 0110:采样频率fSAMPLING=fDTS/4, N=0
  TIM_ICInit(ENCODER_Left_TIMER, &TIM_ICInitStructure);
  
// Clear all pending interrupts
  TIM_ClearFlag(ENCODER_Left_TIMER, TIM_FLAG_Update);
  TIM_ITConfig(ENCODER_Left_TIMER, TIM_IT_Update, ENABLE);
  //Reset counter
  ENCODER_Left_TIMER->CNT = COUNTER_RESET;
  

  
  TIM_Cmd(ENCODER_Left_TIMER, ENABLE);  
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        __nop();
        Left_hEncoder_Timer_Overflow = 0;
        Left_hEncoder_Timer_Overflow_High = 0;
        Left_hRot_Speed = 0;
        Left_ENC_Get_Electrical_Angle(); //第一次不要这个数据!!lastCount
}


s16 Right_ENC_Get_Electrical_Angle(void)
{
        static u16   lastCount = 0;
        u16 curCount ;
        s16 dAngle ;
        static s16 Last_Overflow = 0;
        
        
        curCount = ENCODER_Right_TIMER->CNT;
        dAngle = curCount - lastCount;
        
        //ensure          |Right_hEncoder_Timer_Overflow - Last_Overflow|<=1
        if(Right_hEncoder_Timer_Overflow != Last_Overflow)
        {
                
                if ( (ENCODER_Right_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)   //反转
                {// encoder timer down-counting
                                        dAngle -= ENCODER_TIM_PERIOD;
                
                }
                else  
                {//encoder timer up-counting
                                        
                                dAngle += ENCODER_TIM_PERIOD;
                                
                }
                
        }

        lastCount = curCount;
        Last_Overflow = Right_hEncoder_Timer_Overflow;
        return (s16)dAngle;

}


s16 Left_ENC_Get_Electrical_Angle(void)
{
        static u16   lastCount = 0;
        u16 curCount ;
        s16 dAngle ;
        static s16 Last_Overflow = 0;
        
        
        curCount = ENCODER_Left_TIMER->CNT;
        dAngle = curCount - lastCount;
        
        //ensure          |Left_hEncoder_Timer_Overflow - Last_Overflow|<=1
        if(Left_hEncoder_Timer_Overflow != Last_Overflow)
        {
                
                if ( (ENCODER_Left_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)   //反转
                {// encoder timer down-counting
                                        dAngle -= ENCODER_TIM_PERIOD;
                
                }
                else  
                {//encoder timer up-counting
                                        
                                dAngle += ENCODER_TIM_PERIOD;
                                
                }
                
        }

        lastCount = curCount;
        Last_Overflow = Left_hEncoder_Timer_Overflow;
        return (s16)dAngle;

}

void TIM2_IRQHandler(void)
{  
  
  TIM_ClearFlag(ENCODER_Left_TIMER, TIM_FLAG_Update);

  if ((Left_hEncoder_Timer_Overflow != S16_MAX )&&(Left_hEncoder_Timer_Overflow != S16_MIN ))  
  {
                if ( (ENCODER_Left_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)   //反转
                {// encoder timer down-counting
                        Left_hEncoder_Timer_Overflow--;
                }
                else  
                {//encoder timer up-counting                                
                        Left_hEncoder_Timer_Overflow++;
                }

  }
        if(Left_hEncoder_Timer_Overflow == S16_MAX)
        {
                Left_hEncoder_Timer_Overflow = 0;
            Left_hEncoder_Timer_Overflow_High++;
        }
        if(Left_hEncoder_Timer_Overflow == S16_MIN )
        {
                Left_hEncoder_Timer_Overflow = 0;
                Left_hEncoder_Timer_Overflow_High--;

        }
        
}




void TIM3_IRQHandler(void)
{  
  
  TIM_ClearFlag(ENCODER_Right_TIMER, TIM_FLAG_Update);

  if ((Right_hEncoder_Timer_Overflow != S16_MAX )&&(Right_hEncoder_Timer_Overflow != S16_MIN ))  
  {
                if ( (ENCODER_Right_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)   //反转
                {// encoder timer down-counting
                        Right_hEncoder_Timer_Overflow--;

                }
                else  
                {//encoder timer up-counting                                
                        Right_hEncoder_Timer_Overflow++;
                }

  }
        if(Right_hEncoder_Timer_Overflow == S16_MAX)
        {
                Right_hEncoder_Timer_Overflow = 0;
            Right_hEncoder_Timer_Overflow_High++;
        }
        if(Right_hEncoder_Timer_Overflow == S16_MIN )
        {
                Right_hEncoder_Timer_Overflow = 0;
                Right_hEncoder_Timer_Overflow_High--;

        }


关键字:STM32  正交编码器  位置环  速度环

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
浅谈AVR中定时器几种工作模式