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

2024-09-04 08:28

本文主要是介绍【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;				//选择配置定时器通道1TIM_ICInitStructure.TIM_ICFilter = 0xF;							//输入滤波器参数,可以过滤信号抖动TIM_ICInit(TIM3, &TIM_ICInitStructure);							//将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;				//选择配置定时器通道2TIM_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_Hvoid Encoder_Init(void);
int16_t Encoder_Get(void);#endif

Encoder.c

#include "stm32f10x.h"                  // Device headervoid 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);}
}

这篇关于【STM32】通用定时器TIM(编码器接口)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135503

相关文章

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

详解Python中通用工具类与异常处理

《详解Python中通用工具类与异常处理》在Python开发中,编写可重用的工具类和通用的异常处理机制是提高代码质量和开发效率的关键,本文将介绍如何将特定的异常类改写为更通用的ValidationEx... 目录1. 通用异常类:ValidationException2. 通用工具类:Utils3. 示例文

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密