STM32编码器接口

时间:2024-10-16 07:16:15

一、概述

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);  //更新中断就是产生一个中断标志位
	}


}