STM32编码器接口

一、概述

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:

cpp 复制代码
#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:

cpp 复制代码
#ifndef _TIMER_H
#define _TIMER_H


void Timer_Init(void);



#endif
  • 编码器接口

Encoder.c:

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

cpp 复制代码
#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:

cpp 复制代码
#ifndef _ENCODER_H
#define _ENCODER_H

int16_t Encoder_Get(void);

void Encoder_Init(void);

#endif

main.c:

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


}
相关推荐
7yewh几秒前
嵌入式硬件杂谈(七)IGBT MOS管 三极管应用场景与区别
驱动开发·嵌入式硬件·mcu·物联网·硬件架构·硬件工程·pcb工艺
raysync88830 分钟前
半导体企业内外网数据摆渡技术实现方案
单片机·嵌入式硬件
m0_748235952 小时前
LWIP(stm32+lwip+freertos)
stm32·单片机·嵌入式硬件
小鱼做毕设2 小时前
单片机实物成品-008 智能浇花系统
单片机·嵌入式硬件
程序员JerrySUN3 小时前
BitBake 执行流程深度解析:从理论到实践
linux·开发语言·嵌入式硬件·算法·架构
RFID舜识物联网3 小时前
RFID智能文件柜:高效安全的档案管理新方案
大数据·网络·人工智能·嵌入式硬件·物联网
1101 11014 小时前
STM32-笔记12-实现SysTick模拟多线程流水灯
笔记·stm32·嵌入式硬件
美式小田4 小时前
Cadence学习笔记 12 PCB初始化设置
笔记·嵌入式硬件·学习·cadence
思为无线NiceRF5 小时前
新品:SA628F39大功率全双工音频传输模块
单片机·嵌入式硬件·音视频
沐欣工作室_lvyiyi10 小时前
基于单片机的蓄电池内阻检测系统设计(论文+源码)
stm32·单片机·嵌入式硬件·物联网·智能家居