一、TIM3支持正交编码器模式说明
STM32F407的TIM3通用定时器 支持正交编码器接口模式 (Encoder Interface Mode),可自动解析增量式编码器的A/B相正交信号,实现方向识别 与位置计数 ,无需CPU干预。该模式适用于电机控制、机器人关节反馈等场景,具有硬件自动解码 、高实时性 、低CPU占用等优点。
二、硬件连接
1. 引脚分配(TIM3_CH1/CH2)
TIM3的CH1 (A相)与CH2 (B相)引脚需连接编码器的A/B相输出,具体引脚需参考STM32F407的 datasheet(如PB4 =TIM3_CH1、PB5 =TIM3_CH2,需配置为复用功能)。
2. 编码器选择
推荐使用增量式正交编码器 (如E6B2-CWZ1X),输出A/B相正交信号(相位差90°),支持4倍频(每转脉冲数×4),提升分辨率。
3. 硬件滤波
编码器信号易受电磁干扰,建议在A/B相引脚添加RC低通滤波 (如1kΩ电阻+100nF电容),或在TIM3的输入捕获滤波器(ICxF位)中设置滤波参数(如IC1F=0b100,即连续8个时钟周期稳定后视为有效边沿)。
三、软件配置(HAL库)
1. 初始化步骤
(1)使能时钟
c
__HAL_RCC_TIM3_CLK_ENABLE(); // 使能TIM3时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟(假设CH1=PB4、CH2=PB5)
(2)配置GPIO为复用功能
c
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5; // PB4=TIM3_CH1、PB5=TIM3_CH2
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
GPIO_InitStruct.Pull = GPIO_PULLUP; // 内部上拉(防悬空)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速响应
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3; // AF2对应TIM3
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
(3)配置TIM3为编码器模式
c
TIM_Encoder_InitTypeDef Encoder_Config = {0};
Encoder_Config.EncoderMode = TIM_ENCODERMODE_TI12; // 双通道正交解码(4倍频)
Encoder_Config.IC1Polarity = TIM_ICPOLARITY_RISING; // A相上升沿触发
Encoder_Config.IC1Selection = TIM_ICSELECTION_DIRECTTI; // 直接映射到TI1
Encoder_Config.IC1Prescaler = TIM_ICPSC_DIV1; // 不分频
Encoder_Config.IC1Filter = 0x0F; // 数字滤波(15个时钟周期)
Encoder_Config.IC2Polarity = TIM_ICPOLARITY_RISING; // B相上升沿触发
Encoder_Config.IC2Selection = TIM_ICSELECTION_DIRECTTI; // 直接映射到TI2
Encoder_Config.IC2Prescaler = TIM_ICPSC_DIV1; // 不分频
Encoder_Config.IC2Filter = 0x0F; // 数字滤波(15个时钟周期)
TIM_HandleTypeDef htim3;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0; // 不分频(定时器时钟=系统时钟)
htim3.Init.CounterMode = TIM_COUNTERMODE_UPDOWN; // 双向计数(支持正反转)
htim3.Init.Period = 0xFFFF; // 自动重载值(16位最大值,防止溢出)
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分割(不分频)
HAL_TIM_Encoder_Init(&htim3, &Encoder_Config);
(4)启动编码器模式
c
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); // 启动TIM3的CH1/CH2通道
2. 关键配置说明
-
EncoderMode :
TIM_ENCODERMODE_TI12表示双通道正交解码(4倍频),即A/B相的上升沿/下降沿均触发计数,分辨率为编码器线数×4。 -
ICxPolarity:设置A/B相的触发极性(上升沿/下降沿),需与编码器输出信号匹配。
-
ICxFilter :数字滤波器,用于抑制高频噪声(如设置
IC1F=0x0F,则表示输入信号需在连续15个定时器时钟周期内保持稳定,才被视为有效边沿)。 -
CounterMode :
TIM_COUNTERMODE_UPDOWN表示双向计数,正转时计数器递增,反转时递减,支持正反转判断。
参考代码 STM32F407------TIM3正交编码器 www.youwenfan.com/contentcss/182574.html
四、数据读取与方向判断
1. 读取计数值
通过__HAL_TIM_GET_COUNTER()宏读取TIM3的CNT寄存器 (当前计数值),该值反映了编码器的相对位置(正转递增、反转递减)。
c
int16_t current_count = (int16_t)__HAL_TIM_GET_COUNTER(&htim3); // 转换为有符号整数(支持正负)
2. 判断方向
通过__HAL_TIM_IS_TIM_COUNTING_DOWN()宏判断计数方向(1=反转、0=正转),或读取TIM3->CR1寄存器的DIR位 (1=反转、0=正转)。
c
if (__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3)) {
// 反转
} else {
// 正转
}
五、应用示例(电机位置控制)
1. 场景说明
使用TIM3读取电机编码器的A/B相信号,实现电机位置闭环控制(如控制电机旋转至指定角度)。
2. 代码示例
c
#define TARGET_ANGLE 90 // 目标角度(°)
#define ENCODER_RESOLUTION 1000 // 编码器线数(PPR)
#define GEAR_RATIO 10 // 齿轮减速比(电机转10圈,输出轴转1圈)
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init(); // 初始化TIM3为编码器模式
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); // 启动编码器
int32_t current_position = 0; // 当前位置(输出轴角度)
int32_t target_position = TARGET_ANGLE * ENCODER_RESOLUTION * GEAR_RATIO / 360; // 目标位置(编码器脉冲数)
while (1) {
// 读取当前计数值
int16_t count = (int16_t)__HAL_TIM_GET_COUNTER(&htim3);
// 计算输出轴角度(°):(count * 360) / (ENCODER_RESOLUTION * GEAR_RATIO)
current_position = (count * 360) / (ENCODER_RESOLUTION * GEAR_RATIO);
// 位置闭环控制(如PID调节)
if (current_position < target_position) {
// 正转(驱动电机)
} else if (current_position > target_position) {
// 反转(驱动电机)
} else {
// 停止电机
}
HAL_Delay(10); // 10ms循环周期
}
}
六、注意事项
1. 溢出处理
TIM3是16位定时器 ,计数值范围为-32768~32767(双向计数),当计数值超过该范围时会溢出。需通过溢出中断 (TIM_IT_Update)处理溢出,或使用32位定时器(如TIM2/TIM5)扩展计数范围。
2. 抗干扰措施
-
硬件 :编码器信号线使用屏蔽双绞线 ,远离动力线;添加RC滤波电路(如1kΩ电阻+100nF电容)。
-
软件 :启用TIM3的输入滤波器 (
ICxF位),设置合适的滤波参数(如IC1F=0x0F)。
3. 方向判断
需确保编码器A/B相的相位差 为90°,否则方向判断会出错。可通过示波器观察A/B相信号,调整ICxPolarity参数(如TIM_ICPOLARITY_FALLING)。
七、总结
STM32F407的TIM3正交编码器模式为增量式编码器的信号处理提供了硬件级解决方案 ,具有高实时性 、低CPU占用 、易配置等优点。通过合理配置GPIO、定时器参数,可实现电机位置/速度的精准控制,适用于工业自动化、机器人等领域。