正交编码器测速

更新时间:2024-03-28 11:33:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

/******************** (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 #include \#include \#include \

/* Private variables ---------------------------------------------------------*/

s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE], hRot_Speed; //static s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE]; static u8 bSpeed_Buffer_Index = 0;

static volatile u16 hEncoder_Timer_Overflow;

#define TRUE 1 #define FALSE 0

static unsigned char bIs_First_Measurement = TRUE;

/*******************************************************************************

* 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_IN_FLOATING; 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 //72M捕获? 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_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

TIM2->CNT = COUNTER_RESET;

ENC_Clear_Speed_Buffer();

TIM_Cmd(ENCODER_TIMER, ENABLE); }

/*******************************************************************************

* 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)(4294967295 / (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

hSpeed_Buffer[i] = 0; }

bIs_First_Measurement = TRUE; }

/*******************************************************************************

* 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,wtemp_1=0; 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

// wtemp += hSpeed_Buffer[i]; // }

// wtemp /= SPEED_BUFFER_SIZE;

for (i=0;i

if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE)

{

bSpeed_Buffer_Index = 0; }

wtemp = ENC_Calc_Rot_Speed();

hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp; bSpeed_Buffer_Index++;

wtemp_1 += wtemp; }

wtemp_1 /= SPEED_BUFFER_SIZE;

hRot_Speed = ((s16)(wtemp_1)); }

/*******************************************************************************

* 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

*******************************************************************************/

//void LCD_Display(DisplayType DisplayStatus) //{

// u16 hValue; // s16 Theta; // s16 hSpeed; // char *pstr; //

// switch (DisplayStatus) // {

// case DISPLAY_TIMCNT:

// hValue = TIM_GetCounter(ENCODER_TIMER); // LCD_ShowNum(0,0,(hValue),5);

// printf(\// break; //

// case DISPLAY_THETA:

// Theta = ENC_Get_Electrical_Angle()*360/65535; //U16_MAX; // if (Theta < 0)

// {

// hValue = (u16)(-Theta); //// pstr = int2char(hValue); // *pstr = '-'; // } // else // {

// hValue = (u16)Theta; //// pstr = int2char(hValue); // if (hValue != 0) *pstr = '+'; // }

// LCD_ShowChar(0,8,*pstr);

// LCD_ShowNum(0,9,hValue,5); // break; //

// default:

// hSpeed = hRot_Speed; // if (hSpeed < 0) // {

// hValue = (u16)(-hSpeed); //// pstr = int2char(hValue); // *pstr = '-'; // } // else // {

// hValue = (u16)hSpeed; //// pstr = int2char(hValue); // if (hValue != 0) *pstr = '+'; // }

// LCD_ShowChar(0,8,*pstr); // LCD_ShowNum(1,0,*pstr,5); // 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 != 65535) {

hEncoder_Timer_Overflow++; } }

//寄存器版本

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

//#include \

//void Encoder_Init(void) //{

// /* TIM3 clock source enable */

// RCC->APB1ENR|=1<<1; //TIM3时钟使能 // /* Enable GPIOA, clock */

// RCC->APB2ENR|=1<<2; //使能PORTA时钟

// /* Configure PA.06,07 as encoder input */ // GPIOA->CRL&=0XF0FFFFFF;//PA6

// GPIOA->CRL|=0X04000000;//浮空输入 // GPIOA->CRL&=0X0FFFFFFF;//PA7

// GPIOA->CRL|=0X40000000;//浮空输入

// /* Enable the TIM3 Update Interrupt */ // //这两个东东要同时设置才可以使用中断

// TIM3->DIER|=1<<0; //允许更新中断 // TIM3->DIER|=1<<6; //允许触发中断 // MY_NVIC_Init(1,3,TIM3_IRQChannel,2);

// /* Timer configuration in Encoder mode */ // TIM3->PSC = 0x0;//预分频器

// TIM3->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值

// TIM3->CR1 &=~(3<<8);// 选择时钟分频:不分频

// TIM3->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式 //

// TIM3->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1 // TIM3->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2

// TIM3->CCER &= ~(1<<1); //CC1P='0' IC1FP1不反相,IC1FP1=TI1 // TIM3->CCER &= ~(1<<5); //CC2P='0' IC2FP2不反相,IC2FP2=TI2 // TIM3->CCMR1 |= 3<<4; // IC1F='1000' 输入捕获1滤波器

// TIM3->SMCR |= 3<<0; //SMS='011' 所有的输入均在上升沿和下降沿有效

// TIM3->CNT = COUNTER_RESET;

// TIM3->CR1 |= 0x01; //CEN=1,使能定时器 //}

1. #ifndef __ENCODER_H__ 2. #define __ENCODER_H__ 3.

4. #include \5.

6. //void Encoder_Init(void); 7.

8. //#endif 9.

10. /******************** (C) COPYRIGHT 2007 STMicroelectronics ************

********

11. * File Name : stm32f10x_encoder.h 12. * Author : IMS Systems Lab 13. * Date First Issued : 21/11/07

14. * Description : This file contains the software implementation fo

r the

15. * encoder position and speed reading.

16. ***********************************************************************

********* 17. * History:

18. * 21/11/07 v1.0

19. ***********************************************************************

*********

20. * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUST

OMERS

21. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO

SAVE TIME.

22. * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIREC

T,

23. * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING F

ROM THE

24. * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODIN

G

25. * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 26. ***********************************************************************

********/ 27.

28. /* Define to prevent recursive inclusion -------------------------------------*/ 29. 30.

31. /* Private typedef -----------------------------------------------------------*/

32. typedef enum {DISPLAY_TIMCNT = 0,DISPLAY_THETA,DISPLAY_W} DisplayType; 33.

34. /* Private typedef -----------------------------------------------------------*/

35. /* Private define ------------------------------------------------------------*/

36. #define ENCODER_TIMER TIM3 // Encoder unit connected to TIM3

37. #define ENCODER_PPR (u16)(200) // number of pulses per revol

ution

38. #define SPEED_BUFFER_SIZE 2//8 39.

40. #define COUNTER_RESET (u16)0

41. #define ICx_FILTER (u8) 6 // 6<-> 670nsec 42.

43. #define TIMx_PRE_EMPTION_PRIORITY 1 44. #define TIMx_SUB_PRIORITY 0 45.

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

48. extern s16 hRot_Speed; 49. 50.

51. /* Private functions ---------------------------------------------------------*/

52. s16 ENC_Calc_Rot_Speed(void); 53. 54.

55. /* Includes ------------------------------------------------------------------*/

56. /* Private define ------------------------------------------------------------*/

57. #define SPEED_SAMPLING_TIME 9 // (9+1)*500usec = 5msec 58.

59. /* Exported functions ------------------------------------------------------- */

60. void ENC_Init(void);

61. s16 ENC_Get_Electrical_Angle(void); 62. void ENC_Clear_Speed_Buffer(void); 63. void ENC_Calc_Average_Speed(void);

64. //void LCD_Display(DisplayType DisplayStatus); 65. s16 ENC_Get_Speed(void);

66. void TIM3_IRQHandler(void);; 67.

68. #endif

69. /*__STM32F10x_ENCODER_H*/

70. /******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF F

ILE****/

本文来源:https://www.bwwdw.com/article/ovsr.html

Top