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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具