[STM32]Day6-Part4编码器接口测速

编码器接口简介

Encoder Interface编码器接口,编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度。

每个高级定时器和通用定时器都拥有一个编码器接口,两个输入引脚借用了输入捕获通道的通道1和通道2。

正交编码器一般可以测量位置,或者带有方向的速度值。正反转方向可以根据AB相信号再某一时刻的状态来判断,具体如图中右表。

编码器测速原理

编码器AB相分别接TIMx_CH1和TIMx_CH2,经过滤波和边沿检测产生TI1FP1和TI2FP2信号,输入编码器接口。编码器接口的输出信号,控制CNT的计数时钟和计数方向,此时内部时钟源、时基单元初始化设置的计数方向不起作用。

编码器接口基本结构

编码器模式下上升沿和下降沿都是有效的,因此极性选择不再是选择上升沿/下降沿,而是是否让TI1/TI2信号经过非门进行反转,也叫反相。

工作模式

在TI1和TI2上计数的精度较高。

下面是TI1和TI2均不反相时的编码器模式实例。

毛刺部分前后计数器的值不变,体现了使用正交信号抗噪能力强的特点。

下面是TI1经过反相时编码器模式实例

编码器接口测速

整体流程:配置GPIO -> 配置时基单元 -> 配置输入捕获单元 -> 配置编码器接口 -> TIM_cmd使能计数器

关于输入模式:上拉输入/下拉输入/浮空输入的选择,上拉输入和下拉输入一般由外设的默认电平确定,旋转编码器默认输出高电平,因此PA6和PA7选择上拉输入。

c 复制代码
// RotaryEncoder.c
#include "stm32f10x.h"                  // Device header

int16_t RotaryEncoder_Count;

void RotaryEncoder_Init(void)
{
	// 配置GPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	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);
	
	// 配置时基单元
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;
	TIM_TimeBaseInitStructure.TIM_Period = 1 - 1;
//	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;		计数方向由编码器决定,无需设置
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	// 配置输入捕获单元
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);
	// 通道1
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Rising;		// 不代表上升沿,而是说明不反相
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	// 通道2
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Rising;		// 不代表上升沿,而是说明不反相
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	// 配置编码器接口,
	// TIM_ICPolarity_Rising, TIM_ICPolarity_Rising两个参数与上面配置通道的极性选择配置的是同一个寄存器
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	
	// 使能计数器
	TIM_Cmd(TIM3, ENABLE);
}

int16_t RotaryEncoder_Get(void)
{
//	return TIM_GetCounter(TIM3);		// 显示位置
	int16_t Temp;
	Temp = TIM_GetCounter(TIM3);
	TIM_SetCounter(TIM3, 0);		// 清零CNT
	return Temp;
}

// RotaryEncoder.h
#ifndef __RotaryEncoder_H
#define __ROtaryEncoder_H

void RotaryEncoder_Init(void);
int16_t RotaryEncoder_Get(void);

#endif

// main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED_Software.h"
#include "RotaryEncoder.h"
#include "Timer.h"

int16_t Speed;

int main(void)
{
	
	OLED_Init();
	Timer_Init();
	RotaryEncoder_Init();
	
	OLED_ShowString(1, 1, "Speed:");

	while(1)
	{
		
		OLED_ShowSignedNum(1, 7, Speed, 5);
//		Delay_ms(1000);		// 容易阻塞主程序
	}
}

// 重写中断函数
void TIM2_IRQHandler(void)
{
	// 检查标志位
	if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) {
		Speed = RotaryEncoder_Get();
		// 清除标志位
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
相关推荐
玩转单片机与嵌入式17 小时前
深入浅出TinyML 16:FFT、频带能量和MFCC分别适合什么任务?
stm32·深度学习·tinyml
深圳市宝华视联1 天前
Python 读取 IP 视频流简单 Demo
python·嵌入式硬件·opencv·网络协议·tcp/ip·实时音视频·嵌入式实时数据库
恒锐丰科技韩生1 天前
RB6005A|晶准 单节锂电池内置 MOS 保护芯片 DFN2×3‑8
嵌入式硬件·硬件工程
youshi66681 天前
stm32-PWR、低功耗模式
stm32·单片机·嵌入式硬件
ACP广源盛139246256731 天前
Qwen3.8‑2.4T 开源落地@ACP#国产 Serdes 长距离视频传输芯片 GSV5800 在私有化 AI 服务中的价值与应用场景
大数据·数据库·人工智能·嵌入式硬件·矩阵·开源·音视频
Funing71 天前
STM32 电机动态 PI 控制:从编码器反馈、增量式 PI 到 Matlab 参数拟合与 PWM 输出
stm32·嵌入式硬件·matlab·pi控制算法
云泽8081 天前
深入浅出 STM32(十八):时钟树、总线与寄存器的底层联动机制
stm32·单片机·嵌入式硬件
米饭不加菜1 天前
C51 语言参考手册
经验分享·笔记·单片机·嵌入式硬件
深圳市宝华视联1 天前
院感约束下,手术室音视频布线与设备摆放实施注意事项
嵌入式硬件·音视频·实时音视频·视频编解码·嵌入式实时数据库
科芯创展1 天前
2.7VIN,5VOUT,360KHz,电荷泵升压芯片,XZ3120
单片机