模式STM32 TIM 编码器接口模式实现
文章目录
一、编码器接口简介
自动控制CNT自增或自减
,从而指示编码器的位置、旋转方向和旋转速度1个编码器接口
,C8T6拥有4个编码器接口两个输入引脚借用了输入捕获的通道1和通道2(CH1和CH2引脚)
编码器的速度
。如果只是取出CNT的值不清零,则表示编码器当前的位置
二、正交编码器
三、通用定时器框图
四、编码器接口基本结构
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//配置编码器接口,第二个参数为编码器模式,参数三四为通道的极性
五、工作模式
六、实例(均不反相)
七、实例(TI1反相)
是修改将CH1或2通道内的极性选择,在编码器模式下是高低电平的极性翻转,而不是输入捕获模式下的边沿翻转
八、编码器接口测速
本质:编码器计次,计次可以使用外部中断方式,方波信号来自编码器,在中断函数里面手动计次,占用软件资源,CPU会频繁进入中断,可以采用硬件自动化计次,也就是定时器的编码器接口模式。
使用场景:使用PWM驱动电机,再使用编码器(无接触式的霍尔传感器或光栅)测量电机速度,再用PID算法实现闭环控制
电路设计
旋转编码器的AB相分别接PA6和PA7
关键代码
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
int16_t Speed;
int main(void)
{
OLED_Init();
Timer_Init();
Encoder_Init();
OLED_ShowString(1, 1, "Speed:");
while (1)
{
OLED_ShowSignedNum(1, 7, Speed, 5);//OLED_ShowSignedNum()可以显示负数
//Delay_ms(1000);为了避免在主循环中造成阻塞,可以用定时中断的方式读取CNT的变化值,如TIM2_IRQHandler()函数
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Speed = Encoder_Get();//每隔一秒读取一次速度
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Encoder.c
#include "stm32f10x.h" // Device header
void Encoder_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//因为编码器接口是一个带有方向控制的外部时钟,所以不需要配置时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数模式也是无效,由编码器接口控制
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //PSC,不分频,编码器时钟直接驱动计数器
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//通道1
TIM_ICInitStructure.TIM_ICFilter = 0xF;//滤波器
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//无须定义新的结构体配置成员,因为调用TIM_ICInit()函数后就写入到硬件寄存器中
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;//通道2
TIM_ICInitStructure.TIM_ICFilter = 0xF;//滤波器
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//配置编码器接口,第二个参数为编码器工作模式,参数三四为通道的极性,Falling表示通道反向,Rising表示通道不反向
TIM_Cmd(TIM3, ENABLE);
}
//返回有符号位的16位计数器的值
int16_t Encoder_Get(void)
{
int16_t Temp;
Temp = TIM_GetCounter(TIM3);
TIM_SetCounter(TIM3, 0);
return Temp;
}
参考视频:江科大自化协