STM32控制编码器

一、编码器

1.概述

编码器是一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感器。

可以用来测量位置,测量速度。

2.原理

这里写图片描述

3. 编码器软件四倍频技术

这里写图片描述
四倍频的方法是测量A相和B相的上升沿和下降沿

二、stm32控制编码器

stm32控制编码器可以采用Timer的编码器模式,Tim1~8的CH1和CH2分别对应A相和B相

1.TIMx的编码器接口模式

选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的
SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则
置SMS=011。

通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以
对输入滤波器编程。

两个输入TI1和TI2被用来作为增量编码器的接口。假定计数器已经启动(TIMx_CR1
寄存器中的CEN=’1’),计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。

配置范例:

CC1S=01’ (TIMx_CCMR1寄存器, IC1FP1映射到TI1)
CC2S=01’ (TIMx_CCMR2寄存器, IC2FP2映射到TI2)
CC1P=0’ (TIMx_CCER寄存器, IC1FP1不反相, IC1FP1=TI1)
CC2P=0’ (TIMx_CCER寄存器, IC2FP2不反相, IC2FP2=TI2)
SMS=011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效).
CEN=1’ (TIMx_CR1寄存器,计数器使能)

2.硬件连接

实验采用一款安装了编码盘的直流电机,如图:

STM32控制编码器_第1张图片

带编码器电机        STM32
电机线+     <--->   PB12
电机线-     <--->   PB13
编码器A相   <--->   PA0(TIM2->CH1)
编码器B相   <--->   PA1(TIM2->CH2)
编码器5V    <--->   5V
编码器GND   <--->   GND

三、软件驱动

encode.h:

#ifndef _ENCODE_H
#define _ENCODE_H

#include "sys.h"
#define PWMA   TIM1->CCR1  //PA8
#define BIN1   PBout(13)
#define BIN2   PBout(12)
#define ENCODER_TIM_PERIOD (u16)(65535)   //不可大于65535 因为F103的定时器是16位的
void Encode_Motor_Init();
void Encode_PWM_Init(u16 arr,u16 psc);
void Encode_Encoder_Init();
void Encode_Init();
int Read_Encoder();
void TIM2_IRQHandler(void);
#endif

encode.c:

void Encode_Motor_Init()//PB12 13
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
    GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void Encode_PWM_Init(u16 arr,u16 psc) //PA8(TIM1 CH1)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOA,ENABLE);

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    TIM_TimeBaseStructure.TIM_Period=arr;
    TIM_TimeBaseStructure.TIM_Prescaler=psc;
    TIM_TimeBaseStructure.TIM_ClockDivision=0;
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse=0;
    TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
    TIM_OC1Init(TIM1,&TIM_OCInitStructure);

    TIM_CtrlPWMOutputs(TIM1,ENABLE);
    TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM1,ENABLE);
    TIM_Cmd(TIM1,ENABLE);

}

void Encode_Encoder_Init() //PA0(TIM2 CH1),PA1(TIM2 CH2)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler=0x0;
    TIM_TimeBaseStructure.TIM_Period=ENCODER_TIM_PERIOD;
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

    TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//使用编码器模式3

    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter=10;
    TIM_ICInit(TIM2,&TIM_ICInitStructure);
    TIM_ClearFlag(TIM2,TIM_FLAG_Update);
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

    TIM_SetCounter(TIM2,0);
    TIM_Cmd(TIM2,ENABLE);
}
void Encode_Init()
{
    Encode_Motor_Init();
    Encode_PWM_Init(7199,0);
    Encode_Encoder_Init();
}
int Read_Encoder()
{
    int Encoder_TIM;    
        Encoder_TIM= (short)TIM2 -> CNT;  
        TIM2 -> CNT=0; 
        return Encoder_TIM;
}
void TIM2_IRQHandler(void)
{                                   
    if(TIM2->SR&0X0001)//溢出中断
    {                                                   
    }                  
    TIM2->SR&=~(1<<0);//清除中断标志位        
}

你可能感兴趣的:(嵌入式)