[求助] 正交编码器代码问题求助

ning_scapr   2017-7-27 17:43 楼主
最近在学正交编码器,网上找的不明来源的stm32f10x_encoder.c,个人看了一下,感觉还可以,大致看懂了,有些小问题还需要与各位大神讨论。

先贴代码:
先是stm32f10x_encoder.c
  1. /******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
  2. * File Name          : stm32f10x_encoder.c
  3. * Author             : IMS Systems Lab  
  4. * Date First Issued  : 21/11/07
  5. * Description        : This file contains the software implementation for the
  6. *                      encoder unit
  7. ********************************************************************************
  8. * History:
  9. * 21/11/07 v1.0
  10. ********************************************************************************
  11. * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  12. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
  13. * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
  14. * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
  15. * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
  16. * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  17. *******************************************************************************/
  18. /* Includes ------------------------------------------------------------------*/
  19. #include "stm32f10x_lib.h"
  20. #include "stm32f10x_encoder.h"
  21. #include "lcd.h"

  22. /* Private typedef -----------------------------------------------------------*/
  23. /* Private define ------------------------------------------------------------*/
  24. #define ENCODER_TIMER   TIM3  // Encoder unit connected to TIM3
  25. #define ENCODER_PPR           (u16)(400)   // number of pulses per revolution
  26. #define SPEED_BUFFER_SIZE 8

  27. #define COUNTER_RESET   (u16)0
  28. #define ICx_FILTER      (u8) 6 // 6<-> 670nsec

  29. #define TIMx_PRE_EMPTION_PRIORITY 1
  30. #define TIMx_SUB_PRIORITY 0

  31. #define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))

  32. /* Private functions ---------------------------------------------------------*/
  33. s16 ENC_Calc_Rot_Speed(void);

  34. /* Private variables ---------------------------------------------------------*/
  35. static s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE], hRot_Speed;
  36. static u8 bSpeed_Buffer_Index = 0;
  37. static volatile u16 hEncoder_Timer_Overflow;
  38. static bool bIs_First_Measurement = TRUE;

  39. /*******************************************************************************
  40. * Function Name  : ENC_Init
  41. * Description    : General Purpose Timer x set-up for encoder speed/position
  42. *                  sensors
  43. * Input          : None
  44. * Output         : None
  45. * Return         : None
  46. *******************************************************************************/
  47. void ENC_Init(void)
  48. {
  49.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  50.   TIM_ICInitTypeDef TIM_ICInitStructure;
  51.   
  52. /* Encoder unit connected to TIM3, 4X mode */   
  53.   GPIO_InitTypeDef GPIO_InitStructure;
  54.   NVIC_InitTypeDef NVIC_InitStructure;
  55.   
  56.   /* TIM3 clock source enable */
  57.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  58.   /* Enable GPIOA, clock */
  59.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  60.   
  61.   GPIO_StructInit(&GPIO_InitStructure);
  62.   /* Configure PA.06,07 as encoder input */
  63.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  64.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  65.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  66.   
  67.   /* Enable the TIM3 Update Interrupt */
  68.   NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
  69.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;
  70.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
  71.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  72.   NVIC_Init(&NVIC_InitStructure);

  73.   /* Timer configuration in Encoder mode */
  74.   TIM_DeInit(ENCODER_TIMER);
  75.   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  76.   
  77.   TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  // No prescaling
  78.   TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1;  
  79.   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  80.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  81.   TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);

  82.   TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,
  83.                              TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
  84.   TIM_ICStructInit(&TIM_ICInitStructure);
  85.   TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;
  86.   TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);
  87.   
  88. // Clear all pending interrupts
  89.   TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
  90.   TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);
  91.   //Reset counter
  92.   TIM2->CNT = COUNTER_RESET;
  93.   
  94.   ENC_Clear_Speed_Buffer();
  95.   
  96.   TIM_Cmd(ENCODER_TIMER, ENABLE);  
  97. }

  98. /*******************************************************************************
  99. * Function Name  : ENC_Get_Electrical_Angle
  100. * Description    : Returns the absolute electrical Rotor angle
  101. * Input          : None
  102. * Output         : None
  103. * Return         : Rotor electrical angle: 0 -> 0 degrees,
  104. *                                          S16_MAX-> 180 degrees,
  105. *                                          S16_MIN-> -180 degrees                  
  106. *******************************************************************************/
  107. s16 ENC_Get_Electrical_Angle(void)
  108. {
  109.   s32 temp;
  110.   
  111.   temp = (s32)(TIM_GetCounter(ENCODER_TIMER)) * (s32)(U32_MAX / (4*ENCODER_PPR));
  112.   return((s16)(temp/65536)); // s16 result
  113. }

  114. /*******************************************************************************
  115. * Function Name  : ENC_Clear_Speed_Buffer
  116. * Description    : Clear speed buffer used for average speed calculation  
  117. * Input          : None
  118. * Output         : None
  119. * Return         : None
  120. *******************************************************************************/
  121. void ENC_Clear_Speed_Buffer(void)
  122. {   
  123.   u32 i;

  124.   for (i=0;i<SPEED_BUFFER_SIZE;i++)
  125.   {
  126.     hSpeed_Buffer[i] = 0;
  127.   }
  128.   bIs_First_Measurement = TRUE;
  129. }

  130. /*******************************************************************************
  131. * Function Name  : ENC_Calc_Rot_Speed
  132. * Description    : Compute return latest speed measurement
  133. * Input          : None
  134. * Output         : s16
  135. * Return         : Return the speed in 0.1 Hz resolution.                    
  136. *******************************************************************************/
  137. s16 ENC_Calc_Rot_Speed(void)
  138. {   
  139.   s32 wDelta_angle;
  140.   u16 hEnc_Timer_Overflow_sample_one, hEnc_Timer_Overflow_sample_two;
  141.   u16 hCurrent_angle_sample_one, hCurrent_angle_sample_two;
  142.   signed long long temp;
  143.   s16 haux;
  144.   
  145.   if (!bIs_First_Measurement)
  146.   {
  147.     // 1st reading of overflow counter   
  148.     hEnc_Timer_Overflow_sample_one = hEncoder_Timer_Overflow;
  149.     // 1st reading of encoder timer counter
  150.     hCurrent_angle_sample_one = ENCODER_TIMER->CNT;
  151.     // 2nd reading of overflow counter
  152.     hEnc_Timer_Overflow_sample_two = hEncoder_Timer_Overflow;  
  153.     // 2nd reading of encoder timer counter
  154.     hCurrent_angle_sample_two = ENCODER_TIMER->CNT;      

  155.     // Reset hEncoder_Timer_Overflow and read the counter value for the next
  156.     // measurement
  157.     hEncoder_Timer_Overflow = 0;
  158.     haux = ENCODER_TIMER->CNT;   
  159.    
  160.     if (hEncoder_Timer_Overflow != 0)
  161.     {
  162.       haux = ENCODER_TIMER->CNT;
  163.       hEncoder_Timer_Overflow = 0;            
  164.     }
  165.      
  166.     if (hEnc_Timer_Overflow_sample_one != hEnc_Timer_Overflow_sample_two)
  167.     { //Compare sample 1 & 2 and check if an overflow has been generated right
  168.       //after the reading of encoder timer. If yes, copy sample 2 result in
  169.       //sample 1 for next process
  170.       hCurrent_angle_sample_one = hCurrent_angle_sample_two;
  171.       hEnc_Timer_Overflow_sample_one = hEnc_Timer_Overflow_sample_two;
  172.     }
  173.    
  174.     if ( (ENCODER_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)  
  175.     {// encoder timer down-counting
  176.       wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle -
  177.                     (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
  178.     }
  179.     else  
  180.     {//encoder timer up-counting
  181.       wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle +
  182.                     (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
  183.     }
  184.    
  185.     // speed computation as delta angle * 1/(speed sempling time)
  186.     temp = (signed long long)(wDelta_angle * SPEED_SAMPLING_FREQ);
  187.     temp *= 10;  // 0.1 Hz resolution
  188.     temp /= (4*ENCODER_PPR);
  189.         
  190.   } //is first measurement, discard it
  191.   else
  192.   {
  193.     bIs_First_Measurement = FALSE;
  194.     temp = 0;
  195.     hEncoder_Timer_Overflow = 0;
  196.     haux = ENCODER_TIMER->CNT;      
  197.     // Check if Encoder_Timer_Overflow is still zero. In case an overflow IT
  198.     // occured it resets overflow counter and wPWM_Counter_Angular_Velocity
  199.     if (hEncoder_Timer_Overflow != 0)
  200.     {
  201.       haux = ENCODER_TIMER->CNT;
  202.       hEncoder_Timer_Overflow = 0;            
  203.     }
  204.   }
  205.   
  206.   hPrevious_angle = haux;  

  207.   return((s16) temp);
  208. }

  209. /*******************************************************************************
  210. * Function Name  : ENC_Calc_Average_Speed
  211. * Description    : Compute smoothed motor speed based on last SPEED_BUFFER_SIZE
  212.                    informations and store it variable  
  213. * Input          : None
  214. * Output         : s16
  215. * Return         : Return rotor speed in 0.1 Hz resolution. This routine
  216.                    will return the average mechanical speed of the motor.
  217. *******************************************************************************/
  218. void ENC_Calc_Average_Speed(void)
  219. {   
  220.   s32 wtemp;
  221.   u32 i;
  222.   
  223.   wtemp = ENC_Calc_Rot_Speed();
  224.         
  225. /* Compute the average of the read speeds */  
  226.   hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp;
  227.   bSpeed_Buffer_Index++;
  228.   
  229.   if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE)
  230.   {
  231.     bSpeed_Buffer_Index = 0;
  232.   }

  233.   wtemp=0;

  234.   for (i=0;i<SPEED_BUFFER_SIZE;i++)
  235.   {
  236.     wtemp += hSpeed_Buffer[i];
  237.   }
  238.   wtemp /= SPEED_BUFFER_SIZE;
  239.   
  240.   hRot_Speed = ((s16)(wtemp));
  241. }

  242. /*******************************************************************************
  243. * Function Name  : LCD_Display
  244. * Description    : This function handles the display of timer counter, theta and
  245.                     electronical frequency:
  246.                     theta --- resolution: 1 degree;
  247.                     electronical frequency --- resolution: 0.1Hz.
  248. * Input          : None
  249. * Output         : None
  250. * Return         : None
  251. *******************************************************************************/
  252. void LCD_Display(DisplayType DisplayStatus)
  253. {
  254.   u16 hValue;
  255.   s16 Theta;
  256.   s16 hSpeed;
  257.   char *pstr;
  258.   
  259.   switch (DisplayStatus)
  260.   {
  261.     case DISPLAY_TIMCNT:
  262.       hValue = TIM_GetCounter(ENCODER_TIMER);
  263.       write_string(int2char(hValue));      
  264.     break;
  265.    
  266.     case DISPLAY_THETA:      
  267.       Theta = ENC_Get_Electrical_Angle()*360/U16_MAX;
  268.       if (Theta < 0)
  269.       {
  270.         hValue = (u16)(-Theta);
  271.         pstr = int2char(hValue);
  272.         *pstr = '-';
  273.       }
  274.       else
  275.       {
  276.         hValue = (u16)Theta;
  277.         pstr = int2char(hValue);
  278.         if (hValue != 0) *pstr = '+';  
  279.       }
  280.       write_string(pstr);
  281.     break;
  282.    
  283.     default:
  284.       hSpeed = hRot_Speed;
  285.       if (hSpeed < 0)
  286.       {
  287.         hValue = (u16)(-hSpeed);
  288.         pstr = int2char(hValue);
  289.         *pstr = '-';
  290.       }
  291.       else
  292.       {
  293.         hValue = (u16)hSpeed;
  294.         pstr = int2char(hValue);
  295.         if (hValue != 0) *pstr = '+';  
  296.       }
  297.       write_string(pstr);
  298.     break;
  299.   }
  300. }

  301. /*******************************************************************************
  302. * Function Name  : TIM2_IRQHandler
  303. * Description    : This function handles TIMx Update interrupt request.
  304.                    Encoder unit connected to TIM2
  305. * Input          : None
  306. * Output         : None
  307. * Return         : None
  308. *******************************************************************************/
  309. void TIM3_IRQHandler(void)
  310. {  
  311.   /* Clear the interrupt pending flag */
  312.   TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
  313.   
  314.   if (hEncoder_Timer_Overflow != U16_MAX)  
  315.   {
  316.    hEncoder_Timer_Overflow++;
  317.   }
  318. }

  319. /******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/


再贴代码stm32f10x_encoder.h
  1. /******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
  2. * File Name          : stm32f10x_encoder.h
  3. * Author             : IMS Systems Lab
  4. * Date First Issued  : 21/11/07
  5. * Description        : This file contains the software implementation for the
  6. *                      encoder position and speed reading.
  7. ********************************************************************************
  8. * History:
  9. * 21/11/07 v1.0
  10. ********************************************************************************
  11. * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  12. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
  13. * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
  14. * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
  15. * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
  16. * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  17. *******************************************************************************/

  18. /* Define to prevent recursive inclusion -------------------------------------*/
  19. #ifndef __STM32F10x_ENCODER_H
  20. #define __STM32F10x_ENCODER_H

  21. /* Private typedef -----------------------------------------------------------*/
  22. typedef enum {DISPLAY_TIMCNT = 0,DISPLAY_THETA,DISPLAY_W} DisplayType;

  23. /* Includes ------------------------------------------------------------------*/
  24. /* Private define ------------------------------------------------------------*/
  25. #define SPEED_SAMPLING_TIME  9     // (9+1)*500usec = 10msec

  26. /* Exported functions ------------------------------------------------------- */
  27. void ENC_Init(void);
  28. s16 ENC_Get_Electrical_Angle(void);
  29. void ENC_Clear_Speed_Buffer(void);
  30. void ENC_Calc_Average_Speed(void);
  31. void LCD_Display(DisplayType DisplayStatus);
  32. s16 ENC_Get_Speed(void);
  33. void TIM3_IRQHandler(void);;

  34. #endif  /*__STM32F10x_ENCODER_H*/
  35. /******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/


我的问题是:
1.定时器初始化的时候
TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;
ICx_FILTER宏定义为6,这里为什么要定义成6?
查看stm32不完全手册
1.jpg
这里是输入捕获的数字滤波器的分频,是fdts的四分之一,并且6个事件有一次触发,这和编码器有什么关系,我定义成别的有关系吗?

2.ENC_Get_Electrical_Angle()函数里面为什么这样计算,小弟不太理解
这里main好多东西感觉宏定义漏掉了
例如 这个函数里的U32_MAX从别的地方知道,应该就是32位无符号数的最大值,就是2^32-1

3.ENC_Calc_Rot_Speed()函数里的down-counting和up-counting之后计算的wDelta_angle方法,为什么要这样计算?一个是加,一个是减。

4.ENC_Calc_Rot_Speed()里用到的SPEED_SAMPLING_FREQ,在前面有宏定义
#define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))
SPEED_SAMPLING_TIME在头文件里有宏定义,是9
这两个宏定义,一个sample time,一个 sample frequency是什么意思?

这些地方小弟不太明白,还望大神们指点。

PS 有大神知道像这种官方的历程应该怎么找吗?在ST官网找不到,在网上论坛有人说是在stmcu.org,我去搜了下,也没有找到。目前这些代码都是百度搜出来的,有大神知道还望告知!

谢谢各位了!

回复评论 (1)

不懂软件,硬件还可以看看。。
点赞  2017-7-28 11:53
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复