打印
[应用相关]

STM32 正交编码器代码

[复制链接]
706|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
drer|  楼主 | 2021-6-5 21:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : stm32f10x_encoder.c
* Author             : IMS Systems Lab  
* Date First Issued  : 21/11/07
* Description        : This file contains the software implementation for the
*                      encoder unit
********************************************************************************
* History:
* 21/11/07 v1.0
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "sys.h"
#include "uart.h"       
#include "systim3.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ENCODER_TIMER                TIM3  // Encoder unit connected to TIM3
#define ENCODER_PPR           (u16)(900)   // number of pulses per revolution
#define SPEED_BUFFER_SIZE               8
#define COUNTER_RESET   (u16)0
#define ICx_FILTER      (u8) 6 // 6<-> 670nsec
#define TIMx_PRE_EMPTION_PRIORITY 1
#define TIMx_SUB_PRIORITY 0
#define SPEED_SAMPLING_FREQ (u16)(1000/(SPEED_SAMPLING_TIME+1))
/* Private functions ---------------------------------------------------------*/
s16 ENC_Calc_Rot_Speed(void);
/* Private variables ---------------------------------------------------------*/
static s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE], hRot_Speed;
static u8 bSpeed_Buffer_Index = 0;
static volatile u16 hEncoder_Timer_Overflow;
static bool bIs_First_Measurement = TRUE;



使用特权

评论回复
沙发
drer|  楼主 | 2021-6-5 21:18 | 只看该作者

/*******************************************************************************
* Function Name  : ENC_Init
* Description    : General Purpose Timer x set-up for encoder speed/position
*                  sensors
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ENC_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef TIM_ICInitStructure;

        /* Encoder unit connected to TIM3, 4X mode */   
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* TIM3 clock source enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  /* Enable GPIOA, clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  GPIO_StructInit(&GPIO_InitStructure);
  /* Configure PA.06,07 as encoder input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Enable the TIM3 Update Interrupt */
  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);
  /* Timer configuration in Encoder mode */
  TIM_DeInit(ENCODER_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_TIMER, &TIM_TimeBaseStructure);

  TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,//TIM_EncoderMode_TI12,
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
  TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;
  TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);

// Clear all pending interrupts
  TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
  TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);
  //Reset counter
  ENCODER_TIMER->CNT = COUNTER_RESET;

  ENC_Clear_Speed_Buffer();

  TIM_Cmd(ENCODER_TIMER, ENABLE);  
}


使用特权

评论回复
板凳
drer|  楼主 | 2021-6-5 21:19 | 只看该作者

/*******************************************************************************
* Function Name  : ENC_Get_Electrical_Angle
* Description    : Returns the absolute electrical Rotor angle
* Input          : None
* Output         : None
* Return         : Rotor electrical angle: 0 -> 0 degrees,
*                                          S16_MAX-> 180 degrees,
*                                          S16_MIN-> -180 degrees                  
*******************************************************************************/
s16 ENC_Get_Electrical_Angle(void)
{
  s32 temp;

  temp = (s32)(TIM_GetCounter(ENCODER_TIMER)) * (s32)(U32_MAX / (4*ENCODER_PPR));
  return((s16)(temp/65536)); // s16 result
}



/*******************************************************************************
* Function Name  : ENC_Clear_Speed_Buffer
* Description    : Clear speed buffer used for average speed calculation  
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ENC_Clear_Speed_Buffer(void)
{   
  u32 i;
  for (i=0;i<SPEED_BUFFER_SIZE;i++)
  {
    hSpeed_Buffer[i] = 0;
  }
  bIs_First_Measurement = TRUE;
}


使用特权

评论回复
地板
drer|  楼主 | 2021-6-5 21:20 | 只看该作者
/*******************************************************************************
* Function Name  : ENC_Calc_Rot_Speed
* Description    : Compute return latest speed measurement
* Input          : None
* Output         : s16
* Return         : Return the speed in 0.1 Hz resolution.                    
*******************************************************************************/
s16 ENC_Calc_Rot_Speed(void)
{   
  s32 wDelta_angle;
  u16 hEnc_Timer_Overflow_sample_one, hEnc_Timer_Overflow_sample_two;
  u16 hCurrent_angle_sample_one, hCurrent_angle_sample_two;
  signed long long temp;
  s16 haux;

  if (!bIs_First_Measurement)
  {
    // 1st reading of overflow counter   
    hEnc_Timer_Overflow_sample_one = hEncoder_Timer_Overflow;
    // 1st reading of encoder timer counter
    hCurrent_angle_sample_one = ENCODER_TIMER->CNT;
    // 2nd reading of overflow counter
    hEnc_Timer_Overflow_sample_two = hEncoder_Timer_Overflow;  
    // 2nd reading of encoder timer counter
    hCurrent_angle_sample_two = ENCODER_TIMER->CNT;      
    // Reset hEncoder_Timer_Overflow and read the counter value for the next
    // measurement
    hEncoder_Timer_Overflow = 0;
    haux = ENCODER_TIMER->CNT;   

    if (hEncoder_Timer_Overflow != 0)
    {
      haux = ENCODER_TIMER->CNT;
      hEncoder_Timer_Overflow = 0;            
    }

    if (hEnc_Timer_Overflow_sample_one != hEnc_Timer_Overflow_sample_two)
    { //Compare sample 1 & 2 and check if an overflow has been generated right
      //after the reading of encoder timer. If yes, copy sample 2 result in
      //sample 1 for next process
      hCurrent_angle_sample_one = hCurrent_angle_sample_two;
      hEnc_Timer_Overflow_sample_one = hEnc_Timer_Overflow_sample_two;
    }

    if ( (ENCODER_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)  
    {// encoder timer down-counting
      wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle -
                    (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
    }
    else  
    {//encoder timer up-counting
      wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle +
                    (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
    }

    // speed computation as delta angle * 1/(speed sempling time)
    temp = (signed long long)(wDelta_angle * SPEED_SAMPLING_FREQ);
    temp *= 10;  // 0.1 Hz resolution
    temp /= (4*ENCODER_PPR);

  } //is first measurement, discard it
  else
  {
    bIs_First_Measurement = FALSE;
    temp = 0;
    hEncoder_Timer_Overflow = 0;
    haux = ENCODER_TIMER->CNT;      
    // Check if Encoder_Timer_Overflow is still zero. In case an overflow IT
    // occured it resets overflow counter and wPWM_Counter_Angular_Velocity
    if (hEncoder_Timer_Overflow != 0)
    {
      haux = ENCODER_TIMER->CNT;
      hEncoder_Timer_Overflow = 0;            
    }
  }

  hPrevious_angle = haux;  

  return((s16) temp);
}


/*******************************************************************************
* Function Name  : ENC_Calc_Average_Speed
* Description    : Compute smoothed motor speed based on last SPEED_BUFFER_SIZE
                   informations and store it variable  
* Input          : None
* Output         : s16
* Return         : Return rotor speed in 0.1 Hz resolution. This routine
                   will return the average mechanical speed of the motor.
*******************************************************************************/
void ENC_Calc_Average_Speed(void)
{   
  s32 wtemp;
  u32 i;

  wtemp = ENC_Calc_Rot_Speed();

/* Compute the average of the read speeds */  
  hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp;
  bSpeed_Buffer_Index++;

  if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE)
  {
    bSpeed_Buffer_Index = 0;
  }
  wtemp=0;
  for (i=0;i<SPEED_BUFFER_SIZE;i++)
  {
    wtemp += hSpeed_Buffer[i];
  }
  wtemp /= SPEED_BUFFER_SIZE;

  hRot_Speed = ((s16)(wtemp));
}


使用特权

评论回复
5
drer|  楼主 | 2021-6-5 21:21 | 只看该作者

/*******************************************************************************
* Function Name  : LCD_Display
* Description    : This function handles the display of timer counter, theta and
                    electronical frequency:
                    theta --- resolution: 1 degree;
                    electronical frequency --- resolution: 0.1Hz.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
#include "stdio.h"
#include "string.h"
       
void LCD_Display(DisplayType PrintfStatus)
{
        u16 hValue;
        s16 Theta;
        s16 hSpeed;
  //char *pstr;

  switch (PrintfStatus)
  {
    case DISPLAY_TIMCNT:
                        hValue = TIM_GetCounter(ENCODER_TIMER);
                        //write_string(int2char(hValue));
                        printf("%d\r\n",hValue);
                        break;   
               
    case DISPLAY_THETA:      
                                Theta = ENC_Get_Electrical_Angle()*360/U16_MAX;
                                if (Theta < 0)
                                {
                                        hValue = (u16)(-Theta);
                                        //pstr = int2char(hValue);
                                        //*pstr = '-';
                                        printf("C=-%04u\r\n",hValue);
                                }
                                else
                                {
                                        hValue = (u16)Theta;
                                        //pstr = int2char(hValue);
                                        //if (hValue != 0) *pstr = '+';
                                        printf("C=+%04u\r\n",hValue);
                                }
                                //write_string(pstr);
            break;   
                               
    default:
                                hSpeed = hRot_Speed;
                                if (hSpeed < 0)
                                {
                                        hValue = (u16)(-hSpeed);
                                        //pstr = int2char(hValue);
                                        //*pstr = '-';
                                        printf("S=-%04u\r\n",hValue);
                                }
                                else
                                {
                                        hValue = (u16)hSpeed;
                                        //pstr = int2char(hValue);
                                        //if (hValue != 0) *pstr = '+';
                                        printf("S=+%04u\r\n",hValue);
                                }
                                //write_string(pstr);
            break;
  }
}


/*******************************************************************************
* Function Name  : TIM2_IRQHandler
* Description    : This function handles TIMx Update interrupt request.
                   Encoder unit connected to TIM2
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void TIM3_IRQHandler(void)
{  
  /* Clear the interrupt pending flag */
  TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);

  if (hEncoder_Timer_Overflow != U16_MAX)  
  {
   hEncoder_Timer_Overflow++;
  }
}
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/



使用特权

评论回复
6
drer|  楼主 | 2021-6-5 21:22 | 只看该作者
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : stm32f10x_encoder.h
* Author             : IMS Systems Lab
* Date First Issued  : 21/11/07
* Description        : This file contains the software implementation for the
*                      encoder position and speed reading.
********************************************************************************
* History:
* 21/11/07 v1.0
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SYSTIM3_H
#define __SYSTIM3_H
/* Private typedef -----------------------------------------------------------*/
typedef enum
{
        DISPLAY_TIMCNT = 0,
        DISPLAY_THETA,
        DISPLAY_W
       
} DisplayType;
/* Includes ------------------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SPEED_SAMPLING_TIME  9     // (9+1)*500usec = 10msec
/* Exported functions ------------------------------------------------------- */
void ENC_Init(void);
s16 ENC_Get_Electrical_Angle(void);
void ENC_Clear_Speed_Buffer(void);
void ENC_Calc_Average_Speed(void);
void LCD_Display(DisplayType DisplayStatus);
s16 ENC_Get_Speed(void);
void TIM3_IRQHandler(void);;
#endif  /*__STM32F10x_ENCODER_H*/
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/


使用特权

评论回复
7
goodluck09876| | 2021-6-6 08:59 | 只看该作者
请问这个有滤波吗》

另外,支持的最高频率是?

使用特权

评论回复
8
goodluck09876| | 2021-6-6 08:59 | 只看该作者
这个应该是有几倍频模式吧?

使用特权

评论回复
9
xinpian101| | 2021-6-6 22:13 | 只看该作者
建议论坛代码可以高光显示啊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

60

主题

3315

帖子

4

粉丝