一、概述

1、Encoder Interface 编码器接口概念

  • 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度
  • 每个高级定时器和通用定时器都拥有1个编码器接口
  • 两个输入引脚借用了输入捕获的通道1和通道2(只能是通道1)
  • 正交编码器:

    其实只测其中一相就能测出速度,两相可以知道编码器正传还是反转。

    编码器接口基本结构:

    2、工作模式

    TI1指的是通道1, TI2指的是通道2。

    TI1和TI2均不反相(反相就是电平翻转):

    TI或TI2反相:

    虽然TI1的波形在图里没有翻转,但是你会发现,TI1上升沿,TI2为低电平,应该为向上计数,而图中是向下计数,所以TI1或TI2反相为反相计数器才会向下计数,可以对着表格测试一下。CNT向上计数表示编码器正转,CNT向下计数表示编码器反转。

    二、用旋转编码器进行手动模拟 

    完整代码如下:

  • 定时器定时1s
  • Timer.c:

    #include "stm32f10x.h"                  // Device header
    
    extern uint16_t Num;
    void Timer_Init(void)
    {
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	//1.配置时钟,用那个外设
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    	
    	//2.内部时钟配置
    	TIM_InternalClockConfig(TIM2);
    	
    	//3.配置时基单元
    	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;     //滤波频率
    	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //计数方式
    	TIM_TimeBaseInitStruct.TIM_Period=10000-1;                 //自动重装载寄存器ARR
    	TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;               //预分频器
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;            //这个是高级定时器才用的,这里不用,给0
    
    	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
    	
    
    	TIM_ClearFlag(TIM2,TIM_FLAG_Update);                        //清除中断标志位
    	//4.配置中断输出控制,打开中断
    	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    	
    	//5.NVIC配置
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    	
    	NVIC_Init(&NVIC_InitStructure);
    	
    	//6.启动定时器
    	TIM_Cmd(TIM2,ENABLE);
    }
    
    
    

    Timer.h:

    #ifndef _TIMER_H
    #define _TIMER_H
    
    
    void Timer_Init(void);
    
    
    
    #endif
  • 编码器接口
  • Encoder.c:

    这里没有考虑定时器溢出情况。

    #include "stm32f10x.h"                  // Device header
    
    
    void Encoder_Init(void)
    {
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_ICInitTypeDef  TIM_ICInitStruct;
    	GPIO_InitTypeDef GPIO_InitStructure;
    	//1.配置时钟,用那个外设
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	
     	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;   
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
     	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    	//2.配置时基单元
    	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;     //滤波频率
    	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //计数方式,向上
    	TIM_TimeBaseInitStruct.TIM_Period=65535-1;                 //自动重装载寄存器ARR,让CNT达到最大量程
    	TIM_TimeBaseInitStruct.TIM_Prescaler=1-1;                  //预分频器
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
    
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
    	
    	//3.初始化捕获单元
    	TIM_ICStructInit(&TIM_ICInitStruct);                          //对结构体进行初始化,防止产生其他影响
    	TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;                   //选择输入通道
    	TIM_ICInitStruct.TIM_ICFilter=0xF;                            //滤波
    	//TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;      //选择极性,上升沿
       TIM_ICInit(TIM3,&TIM_ICInitStruct);
    
      
    	TIM_ICInitStruct.TIM_Channel=TIM_Channel_2;                   //选择输入通道
    	TIM_ICInitStruct.TIM_ICFilter=0xF;                            //滤波
    	//TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;      /选择极性,上升沿,表示电平不反相
       TIM_ICInit(TIM3,&TIM_ICInitStruct);
    	
    	//4.配置编码器接口
       TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12, 
       TIM_ICPolarity_Falling,TIM_ICPolarity_Rising);
    	
    	//5.启动定时器
    	TIM_Cmd(TIM3,ENABLE);
    	
    }
    
    int16_t Encoder_Get(void)
    {
    	int16_t Temp;
    	Temp=TIM_GetCounter(TIM3);
    	TIM_SetCounter(TIM3,0);
        return Temp;   
    
    }
    
    

    Encoder.h:

    #ifndef _ENCODER_H
    #define _ENCODER_H
    
    int16_t Encoder_Get(void);
    
    void Encoder_Init(void);
    
    #endif
    

    main.c:

    #include  "stm32f10x.h"                  // Device header
    #include  "OLED.h"
    #include  "delay.h"
    #include  "Timer.h"
    #include  "Encoder.h"
    
    int16_t speed;
    
    int main(void)
    {
    	
       OLED_Init();
    	Timer_Init();
    	Encoder_Init();
    	OLED_ShowString(1,1,"CNT:");
    	while(1) 
    	{
    
    	   OLED_ShowSignedNum(1,5,speed,5);
    		Delay_ms(1000);
    	}
    	
    }
    
    void TIM2_IRQHandler(void)
    {
    
    	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
    	{
    		
    		speed=Encoder_Get();
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  //更新中断就是产生一个中断标志位
    	}
    
    
    }
    

    作者:GCC_a.out

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32编码器接口

    发表回复