1、编码器接口 ( EnCoder Interface 

  • STM32编码器接口可以接收正交编码器信号,根据正交信号脉冲,自动控制计数器CNT的自增和自减,指示编码器的位置,旋转方向和旋转速度;
  • 高级定时器通用定时器有1个编码器接口,输入引脚借用了输入捕获的通道1和通道2;
  • 软件资源硬件资源:触发中断消耗软件资源;输出比较、输入捕获、编码器接口属于硬件资源;

 

2、正交编码器(正交信号抗噪声

  • 正交编码器(也称为增量编码器)是一种机电传感器,通过两个正交的输出信号(通常称为A相和B相)来提供位置信息。
  • 这两个信号相位差为90度,通过监控脉冲的数目和两个信号的相对相位,可以跟踪旋转位置、旋转方向和速度

     

 

3、编码器接口的设计逻辑

     A相和B相的边沿作为计数器的计数时钟,出现边沿信号时,就出现自增或者自减;

     A相呈上升沿/下降沿时,判断B相的高低电平,如果B相状态上表,则自增;如果B相状态下表,则自减;

 

4、编码器接口的电路

   

  • CH1 ----> 输入滤波器----> 边沿检测器----> 极性选择(表示高低电平的极性)----> TI1FP1 ---->编码器接口 ---->时基单元
  • CH2 ----> 输入滤波器----> 边沿检测器----> 极性选择(表示高低电平的极性)----> TI2FP2 ---->编码器接口 ---->时基单元

     

 

工作模式

 

编码器接口测速实验

编码器模块 EnCoder.c

#include "stm32f10x.h"

void EnCoder_Init(void)
{
    /* 开启时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* 配置GPIO */
    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_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1;   //预分频值
	TIM_TimeBaseInitStruct.TIM_Period = 65536 -1;    //  自动重装值
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV2;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; 
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);  

    /* 配置输入捕获单元 */
    TIM_ICInitTypeDef    TIM_ICInitStruct;
    TIM_ICStructInit(&TIM_ICInitStruct);
    
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStruct.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM3, &TIM_ICInitStruct);
    
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStruct.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM3, &TIM_ICInitStruct);

    /* 配置编码器接口模式,输入捕获通道TI1和TI2都计数 */
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Rising);

    /* 启用定时器 */
    TIM_Cmd(TIM3, ENABLE);
}


int16_t EnCoder_Get(void)
{
    int16_t Tmp = 0;
    Tmp = TIM_GetCounter(TIM3);
    TIM_SetCounter(TIM3, 0);
    return Tmp;
}

定时器模块 Timer.c

#include "stm32f10x.h"                  // Device header

extern uint16_t uiNum;

void Timer_Init(void)
{
	/* RCC开始TIM2定时器的时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/*  RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
 *  RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
 *  RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
 *  RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, 
 *  RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
 *  RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
 *  RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
 */
	
	/* 选择时基单元的时钟 */
	TIM_InternalClockConfig(TIM2);
	
	/* 配置时基单元 */
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200-1;   //预分频值
	TIM_TimeBaseInitStruct.TIM_Period = 1000 -1;    //  自动重装值
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV2;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; 
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	
	/* 使能更新中断至NVIC */
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // TIM_IT_Update 表示更新中断
	
	/* 配置NVIC */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef  NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; 
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);

	/* 启动定时器 */
	TIM_Cmd(TIM2, ENABLE);
}

void TIM2_IRQHandler(void)
{
	if( SET == TIM_GetITStatus(TIM2, TIM_IT_Update) )
	{
		uiNum ++;
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}	

 

主函数模块 main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "EnCoder.h"

uint16_t uiNum = 0;

int main(void)
{
	OLED_Init();	
	Timer_Init();
    EnCoder_Init();
	
	while(1)
	{
		OLED_ShowSignedNum(1, 1, EnCoder_Get(), 4);
		Delay_ms(1000);
	}
}

 

posted on 2025-01-26 21:59  轩~邈  阅读(200)  评论(0)    收藏  举报