stm32-TIM编码器接口

文章介绍了STM32编码器接口的工作原理,包括编码器接口如何根据正交信号自动控制计数器的增减来指示位置和速度。通过编码器接口测速的基本思路是开启时钟、配置GPIO和定时器,然后每隔固定时间读取并清零计数器以测量速度。编码器接口使用输入捕获滤波器和边沿检测,每个高级定时器支持一个编码器接口,可以处理两个输入引脚。文章还涉及了编码器的工作模式和uint16_t转int16_t的补码原理。
摘要由CSDN通过智能技术生成

一、知识点

1.编码器接口(Encoder Interface)

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

例子解释
若初始化之后CNT初始值为0,右转产生8个脉冲后停下来,CNT就从0自增加到8,再让编码器向左转产生5个脉冲,那么CNT就从8自减5至3。
所以编码器接口就相当于一个带有方向控制的外部时钟,它同时控制着CNT的计数时钟和计数方向,CNT的值就表示了编码器的位置
若每隔一段时间取出CNT的值,再把CNT清零,每次取出来的值就表示了编码器的速度

2.资源简介

在这里插入图片描述
编码器接口有使用CH1和CH2的输入捕获滤波器和边沿检测,编码器接口没有使用后面的是否交叉、预分频器、CCR寄存器与编码器接口无关
编码器接口的输出部分:相当于从模式控制器,去控制CNT的计数时钟和计数方向

  • 每个高级定时器和通用定时器都拥有1个编码器接口
  • 两个输入引脚借用了输入捕获的通道1和通道2(通道3和通道4不能用)
  • 如果一个定时器配置为编码器接口模式,则该编码器干不了其他的事,C8T6这一类型芯片只有四个定时器,即最多只能接四个编码器。

3.正交信号

在这里插入图片描述
像这样一个信号比另一个信号慢90度,则这两个信号被称为正交信号

  • 原理
    首先把A相和B相的所有边缘,作为计数器的计数时钟,出现边缘信号时就计数自增或自减,增还是减由另一相的高低电平决定

  • 好处
    a、正交信号精度更高,因为A、B相都可以计次,相当关于计次频率提高了一倍
    b、其次正交信号可以以抗噪声,因为正交信号两个信号必须是交替跳变的,可以设计一个抗噪声电路,如果一个信号不变,另一个信号连续跳变,也就是产生了噪声,这时计次值是不会变化的

4.工作模式

在这里插入图片描述
在TI1和TI2上计数
a.均不反向
在这里插入图片描述

b.TI1反向,TI2不反向
![](https://img-blog.csdnimg.cn/818cd2d29f274909882db47aba37afaf.png)

5.uint16_t和int16_t

想把65535变成-1,则利用补码原则(把uint16_t写成int16_t)

二、实例(编码器接口测速)

1.基本思路

在这里插入图片描述

一、RCC开启时钟,开启GPIO和定时器时钟
二、配置GPIO口
三、配置时基单元(预分频器选择不分频,自动重装选65535,CNT只需要计数就可以)
四、配置输入捕获单元(只需要配置滤波器和极性两个参数)
五、配置编码器接口模式
六、开启定时器(TIM_Cmd)

测量编码器的速度和方向:需要每隔一段固定的闸门时间,取出一次CNT,然后再把CNT清零,这是测频法测量速度

2.代码

Encoder.c

#include "stm32f10x.h"                  // Device header

void Encoder_Init(void)
{
	//RCC开启时钟
	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_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	//配置输入捕获单元
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);  //赋一个初值,防止干扰
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	//后面两个参数为通道1和通道2的电平特性,上升沿:高低电平不反转(编码器上升沿和下降沿都有效)
	
	//配置编码器接口模式
TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
	
	//开启时钟
	TIM_Cmd(TIM3,ENABLE);
}

int16_t Encoder_Get(void)
{
	int16_t temp;
	temp=TIM_GetCounter(TIM3);
	TIM_SetCounter(TIM3,0);
	return temp;
}

main.c

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

int16_t Speed;

int main(void)
{
	OLED_Init();
	Timer_Init();
	Encoder_Init();
	OLED_ShowString(1,1,"Speed:");
	
	while(1)
	{
		OLED_ShowSignedNum(1,7,Speed,5);
	}
}

void TIM2_IRQHandler(void)  //中断读取Speed
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		Speed=Encoder_Get();
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值