TIM编码器接口
编码器接口简介
- Encoder Interface 编码器接口
- 编码器接口可接受增量(正交) 编码器的信号, 根据编码器旋转产生的正交信号脉冲, 自动控制CNT自增或自减, 从而指示编码器的位置、旋转方向和旋转速度
- 每个高级定时器和通用定时器都拥有1个编码器接口
- 两个输入引脚借用了捕获通道的通道1和通道2
使用编码器的意义
- 实际中测电机速度会产生大量脉冲信号, 如果用外部中断, 则会大量占用软件资源, 因此可以用编码器接口测量, 将软件资源节省下来
正交编码器
- 正转和反转都是相对的, 具体情况具体配置极性
编码器接口基本结构
工作模式
- 一般用第三种, 精度比较高
实例(均不反向)
- 可以看到编码器的抗噪声能力比较强
实例(TI1反向)
- 一个输入反向, 计数方向与原来相反
- 通过配置反向, 方便地翻转极性, 达到想要的效果
案例: TIM编码器接口测量速度
说明:
- 用旋转编码器模拟电机的转动
- 仅详说明IC单元配置, 和编码器接口配置
硬件接线
配置IC单元
// 配置IC单元 对CH1和CH2进行配置(这是因为编码器的接口借用了CH1和CH2作为输入通道)
// 只需配置通道和滤波器 其他的有编码器自动托管
//极性在设置编码器时会重复配置(因此这里不配置)
TIM_ICInitTypeDef IC_InitStructure;
TIM_ICStructInit(&IC_InitStructure);
IC_InitStructure.TIM_Channel = TIM_Channel_1;
IC_InitStructure.TIM_ICFilter = 0xF;
TIM_ICInit(TIM3, &IC_InitStructure);
IC_InitStructure.TIM_Channel = TIM_Channel_2;
IC_InitStructure.TIM_ICFilter = 0xF;
TIM_ICInit(TIM3, &IC_InitStructure);
配置编码器接口
// 配置编码器接口
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_EncoderInterfaceConfig参数配置及函数原型
/**
* @brief Configures the TIMx Encoder Interface.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_EncoderMode: specifies the TIMx Encoder Mode.
* This parameter can be one of the following values:
* @arg TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level.
* @arg TIM_EncoderMode_TI2: Counter counts on TI2FP2 edge depending on TI1FP1 level.
* @arg TIM_EncoderMode_TI12: Counter counts on both TI1FP1 and TI2FP2 edges depending
* on the level of the other input.
* @param TIM_IC1Polarity: specifies the IC1 Polarity
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Falling: IC Falling edge.
* @arg TIM_ICPolarity_Rising: IC Rising edge.
* @param TIM_IC2Polarity: specifies the IC2 Polarity
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Falling: IC Falling edge.
* @arg TIM_ICPolarity_Rising: IC Rising edge.
* @retval None
*/
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
整体代码
Encoder.c
#include "stm32f10x.h"
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
// TIM 编码器接口测速
// 2023年3月25日14:29:22
int16_t Speed;
int main(void)
{
OLED_Init();
Timer_Init();
EncoderInterface_Init();
OLED_ShowString(1, 1, "Speed:");
while(1)
{
OLED_ShowSignedNum(1, 7, Speed, 5);
}
}
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Speed = Encoder_Get();
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Timer.c
#include "stm32f10x.h"
// extern uint16_t Num;
void Timer_Init(void)
{
// RCC开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 选择时钟源
TIM_InternalClockConfig(TIM2); // 内部时钟
// 配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 内部时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; // 计数模式
TIM_TimeBaseInitStructure.TIM_Period=10000-1; // 加载到自动重装寄存器的值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1; // 预分频的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; // 重复计数器的值
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //
TIM_ClearFlag(TIM2, TIM_FLAG_Update); // 清除标志
// 使能更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// 配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; // 中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; // 响应优先级
NVIC_Init(&NVIC_InitStructure);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
return;
}
/*
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Num++;
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
main.c
#include "stm32f10x.h"
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
// TIM 编码器接口测速
// 2023年3月25日14:29:22
int16_t Speed;
int main(void)
{
OLED_Init();
Timer_Init();
EncoderInterface_Init();
OLED_ShowString(1, 1, "Speed:");
while(1)
{
OLED_ShowSignedNum(1, 7, Speed, 5);
}
}
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Speed = Encoder_Get();
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
参考资料:
【STM32入门教程-2023持续更新中】 https://www.bilibili.com/video/BV1th411z7sn/?p=20&share_source=copy_web&vd_source=ee06a25b3dfb2900ab707b01fdff6667