STM32定时器编码器模式的使用

1 目的:

定时器的编码器模式可以通过硬件的方式来读取编码器的旋转方向和脉冲数,而不需要软件开销。

 

2 使用示例

__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2):返回 0 或 1 ,代表转动方向

__HAL_TIM_GET_COUNTER(&htim2):返回计数脉冲值

如果想看相同时间间隔的脉冲值,可在获得计数后使用 TIM2->CNT=0; 语句将定时器计数值清零。默认情况下定时器会计满65535后变成0

 初始化定时器编码器配置后,主程序中对编码器使用示例程序如下:

   uint16_t Count;
   uint16_t Diretion;


MX_TIM2_Init();
while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ Diretion = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2); Count = __HAL_TIM_GET_COUNTER(&htim2); printf("转动方向:%d 脉冲数:%d \r\n",Diretion,Count ); if(Count>32768){ Count =65536-Count; } if(Diretion ==0){ printf("转动方向:逆时针"); printf(" 角度:%3.2f\r\n",Count*4.5); } else{ printf("转动方向:顺时针"); printf(" 角度:%3.2f\r\n",Count*4.5); } HAL_Delay(500); }

 

3 模块代码:

 tim.h

#ifndef __tim_H
#define __tim_H
#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern TIM_HandleTypeDef htim2;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_TIM2_Init(void);

/* USER CODE BEGIN Prototypes */

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ tim_H */

 

 tim.c

/* Includes ------------------------------------------------------------------*/

#include "tim.h"

 

/* USER CODE BEGIN 0 */

 

/* USER CODE END 0 */

 

TIM_HandleTypeDef htim2;

 

/* TIM2 init function */

void MX_TIM2_Init(void)

{

  TIM_Encoder_InitTypeDef sConfig = {0};

  TIM_MasterConfigTypeDef sMasterConfig = {0};

 

  htim2.Instance = TIM2;

  htim2.Init.Prescaler = 0;

  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

  htim2.Init.Period = 65535;

  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;

  sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;

  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;

  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;

  sConfig.IC1Filter = 0x0F;

  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;

  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;

  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;

  sConfig.IC2Filter = 0x0F;

  if (HAL_TIM_Encoder_Init(&htim2, &sConfig) != HAL_OK)

  {

    Error_Handler();

  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)

  {

    Error_Handler();

  }

 

}

 

void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)

{

 

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  if(tim_encoderHandle->Instance==TIM2)

  {

  /* USER CODE BEGIN TIM2_MspInit 0 */

 

  /* USER CODE END TIM2_MspInit 0 */

    /* TIM2 clock enable */

    __HAL_RCC_TIM2_CLK_ENABLE();

 

    __HAL_RCC_GPIOA_CLK_ENABLE();

    /**TIM2 GPIO Configuration   

    PA0-WKUP     ------> TIM2_CH1

    PA1     ------> TIM2_CH2

    */

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;

    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

    GPIO_InitStruct.Pull = GPIO_PULLUP;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

  /* USER CODE BEGIN TIM2_MspInit 1 */

 

  /* USER CODE END TIM2_MspInit 1 */

  }

}

 

void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)

{

 

  if(tim_encoderHandle->Instance==TIM2)

  {

  /* USER CODE BEGIN TIM2_MspDeInit 0 */

 

  /* USER CODE END TIM2_MspDeInit 0 */

    /* Peripheral clock disable */

    __HAL_RCC_TIM2_CLK_DISABLE();

 

    /**TIM2 GPIO Configuration   

    PA0-WKUP     ------> TIM2_CH1

    PA1     ------> TIM2_CH2

    */

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);

 

  /* USER CODE BEGIN TIM2_MspDeInit 1 */

 

  /* USER CODE END TIM2_MspDeInit 1 */

  }

}

 

/* USER CODE BEGIN 1 */

 

/* USER CODE END 1 */

 

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

 

}

4 测试结果:

A用一圈20脉冲的编码器进行旋转测试,一开始无反应,检查电路没有上拉电阻,软件配上上拉电阻,可以触发了。

B 配上上拉电阻后,总是有误触发,检查电路AB相没有滤波电容,A,B线上焊接上104滤波电容。

C 计数在0-65535循环,启动时是0,正转,TCN由0递增,反转,TCN由65536(0)递减。

D 正常情况,数据是4的倍数,但是一顿乱转,数据就不是4的倍数,说明有干扰影响到了数据。

E 将sConfig.IC2Filter = 0xF;这样设置后,一顿乱转后的计数明显好转。两个通道都能配置通道滤波。

D 将sConfig.EncoderMode = TIM_ENCODERMODE_TI1;这样设置后,还能分辨正反转,但是计数以2的基数递增。

 

5 输入捕获通道滤波器设置:

Bits 7:4 IC1F: Input capture 1 filter
This bit-field defines the frequency used to sample TI1 input and the length of the digital filter
applied to TI1. The digital filter is made of an event counter in which N consecutive events
are needed to validate a transition on the output:
0000: No filter, sampling is done at fDTS
0001: fSAMPLING=fCK_INT, N=2
0010: fSAMPLING=fCK_INT, N=4
0011: fSAMPLING=fCK_INT, N=8
0100: fSAMPLING=fDTS/2, N=6
0101: fSAMPLING=fDTS/2, N=8
0110: fSAMPLING=fDTS/4, N=6
0111: fSAMPLING=fDTS/4, N=8
1000: fSAMPLING=fDTS/8, N=6
1001: fSAMPLING=fDTS/8, N=8
1010: fSAMPLING=fDTS/16, N=5
1011: fSAMPLING=fDTS/16, N=6
1100: fSAMPLING=fDTS/16, N=8
1101: fSAMPLING=fDTS/32, N=5
1110: fSAMPLING=fDTS/32, N=6
1111: fSAMPLING=fDTS/32, N=8

 

posted @ 2023-10-14 16:27  okyihu  阅读(443)  评论(0编辑  收藏  举报