模式STM32 TIM 编码器接口模式实现

文章目录

  • 一、编码器接口简介
  • 二、正交编码器
  • 三、通用定时器框图
  • 四、编码器接口基本结构
  • 五、工作模式
  • 六、实例(均不反相)
  • 七、实例(TI1反相)
  • 八、编码器接口测速
  • 电路设计
  • 关键代码
  • 一、编码器接口简介

  • Encoder Interface 编码器接口
  • 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度
  • 每个高级定时器和通用定时器都拥有1个编码器接口,C8T6拥有4个编码器接口
  • 两个输入引脚借用了输入捕获的通道1和通道2(CH1和CH2引脚)
  • 编码器接口可以看做是带有方向控制的外部时钟
  • 实际上是测频法测正交脉冲的频率,可以根据旋转方向,实现自增计次,自减计次,然后每隔一段时间取一次CNT的值,再把CNT清零,每次取出来的就是编码器的速度。如果只是取出CNT的值不清零,则表示编码器当前的位置
  • 外部中断实现的效果和编码器接口实现的效果相同,区别是后者使用硬件资源取代软件资源开销
  • 二、正交编码器

  • 可以测量位置(返回CNT的值),或带方向的速度值(返回CNT的变化值)
  • 旋转越快,频率越高,频率代表速度
  • 设计正交信号可以抗噪声
  • 由右侧的图可知,A相上升沿的时候,B相在正传和反转时是不同的电平。所以,将A相和B相的所以边沿作为计数器的时钟,出现边沿变化时,计数器就自增或自减
  • 三、通用定时器框图

  • 编码器接口的两个输入引脚借用了输入捕获的通道的CH1和CH2引脚
  • 编码器接口是从模式控制器,通路连接到CNT计数器
  • 72MHZ的内部时钟和时基单元初始化设置的计数方向并不会使用,而是受到编码器控制
  • 四、编码器接口基本结构

  • ARR自动重装器设置为65535。利用补码特性得到负数,将16位的无符号数转化为16位的有符号数,65535为-1,65534为-2。
  • 函数TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//配置编码器接口,第二个参数为编码器模式,参数三四为通道的极性
  • 边沿检测:上升沿有效表示的是高低电平不翻转,下降沿有效表示翻转高低电平
  • 五、工作模式

  • 四倍频技术
  • 左侧的有效边沿为3种工作模式:由于在判断为正转时可以有四种状态,也就是AB相都可以用来判断,仅仅采用一个通道进行判断也可以只是计次精度会下降
  • 六、实例(均不反相)

  • 一个引脚不变,另一个引脚多次变化的毛刺信号,计数值还是原来那个数
  • 七、实例(TI1反相)

  • TI1反相,在分析前先将TI1的时序图翻转
  • 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;
    }
    
    

    参考视频:江科大自化协

    物联沃分享整理
    物联沃-IOTWORD物联网 » 模式STM32 TIM 编码器接口模式实现

    发表评论