【STM32】通用定时器TIM(编码器接口)

本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发

目录

前言  

编码器接口简介

正交编码器 

编码器接口配置

初始化IO口

输入捕获配置

编码器接口初始化

编码器接口测速代码

Encoder.h

Encoder.c

main.c


前言  

建议先阅读这篇博客,理解定时器输入捕获的配置和旋转编码器的使用

【STM32】通用定时器TIM(输入捕获)-CSDN博客

旋转编码器模块(软件消抖)-CSDN博客

通过外部中断的方式处理编码器信号固然可以,而且任意两个可配置外部中断的GPIO口都可以进行,但是,如果处理转得非常快的电机的旋转编码器,那就会因为频发触发中断, 占用太多CPU软件计算资源,导致其他任务无法正常执行,而且电机太快的话 ,还很有可能软件处理跟不上 ,导致丢步问题。这节我们来使用定时器的编码器接口处理信号。

编码器接口简介

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

每个高级定时器和通用定时器都有1个编码器接口

两个输入引脚借用了输入捕获的通道1通道2

编码器框图 

STM32F10xxx通用定时器为TIM2TIM3TIM4TIM5 

正交编码器 

正交编码器正反转由自己定义

编码器正交波形动态展示视频时间段为00:50至1:57旋转编码器|从零开始认识各种传感器_哔哩哔哩_bilibili

编码器接口配置

初始化IO口

GPIO的其它参数的理解可以阅读下方博客,这里不再赘述。

【STM32】GPIO和AFIO标准库使用框架_gpio afio-CSDN博客

 查找引脚定义表,将通用定时器3的输入捕获通道1(PA6)和通道2(PA7)配置为上拉输入,由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);

输入捕获配置

	
	TIM_ICInitTypeDef TIM_ICInitStructure;							//定义结构体变量
	TIM_ICStructInit(&TIM_ICInitStructure);							//结构体初始化,若结构体没有完整赋值
																	//则最好执行此函数,给结构体所有成员都赋一个默认值
																	//避免结构体初值不确定的问题
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;				//选择配置定时器通道1
	TIM_ICInitStructure.TIM_ICFilter = 0xF;							//输入滤波器参数,可以过滤信号抖动
	TIM_ICInit(TIM3, &TIM_ICInitStructure);							//将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道

	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;				//选择配置定时器通道2
	TIM_ICInitStructure.TIM_ICFilter = 0xF;							//输入滤波器参数,可以过滤信号抖动
    TIM_ICInit(TIM3, &TIM_ICInitStructure);							//将结构体变量交给 TIM_ICInit,配置TIM3的输入捕获通道
    

编码器接口初始化

编码器接口基本结构


	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	//高低电平极性不反转,这个和TIM_ICInit中配置一样,重复覆盖配置
																	//配置编码器模式以及两个输入通道是否反相
																	//注意此时参数的Rising和Falling已经不代表上升沿和下降沿了,而是代表是否反相
//此函数必须在输入捕获初始化之后进行,否则输入捕获的配置会覆盖此函数的部分配置

参数二: 

TIM_EncoderMode描述
TIM_EncoderMode_TI1使用 TIM 编码模式 1
TIM_EncoderMode_TI2使用 TIM 编码模式 2
TIM_EncoderMode_TI12使用 TIM 编码模式 3

TIM_EncoderMode:

计数方向 

编码器接口接管CNT计数器的计数模式,时基单元配置的计数模式设置无效 

编码器接口测速代码

每隔固定时间(可用定时器中断来操作),读取一次编码器接管的CNT计数器,获取增量值,速度=增量值/固定时间

这个速度是CNT计数器计数的速度,比如旋转编码器向右拧一个段落,(本节代码是四次边沿变化都计数,即编码器模式3),定时器捕获到四次计数边沿,编码器接口控制CNT计数器的四次计数都增加或减少。

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int16_t Encoder_Get(void);

#endif

Encoder.c

#include "stm32f10x.h"                  // Device header

void Encoder_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	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);
		
	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,值要大,避免CNT计数器溢出
	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_ICInit(TIM3, &TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	
	TIM_Cmd(TIM3, ENABLE);
}

/**
  * 函    数:获取编码器的增量值
  * 参    数:无
  * 返 回 值:自上此调用此函数后,编码器的增量值
  */
int16_t Encoder_Get(void)
{
	/*使用Temp变量作为中继,目的是返回CNT后将其清零*/
	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 "Encoder.h"

int16_t Speed;

int main(void)
{
	OLED_Init();
	Encoder_Init();
	
	OLED_ShowString(1, 1, "Speed:");
	
	while (1)
	{
		Speed = Encoder_Get();
		Delay_ms(1000);
		OLED_ShowSignedNum(1, 7, Speed, 5);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值