STM32标准库——(9)TIM编码器接口

1.编码器接口简介

  • Encoder Interface 编码器接口
  • 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度
  • 每个高级定时器和通用定时器都拥有1个编码器接口
  • 两个输入引脚借用了输入捕获的通道1和通道2

2.正交编码器

  1. 编码器接口 相当于一个带有方向控制的外部时钟 它同时控制着CNT的计数时钟和计数方向
  2. 旋转速度:当编码器的旋转轴转起来时 A相和B相就会输出这样的方波信号 转得越快 这个方波的频率就越高 所以方波的频率就代表了速度
  3. 旋转方向:当正转时A相提前B相90度 反转时A相滞后B相90度 当然这个正转是A相提前还是A相滞后 并不是绝对的 这只是一个极性问题 毕竟正转和反转的定义也是相对的 总之就是朝一个方向转 是A相提前 另一个方向是A相滞后

3.编码器基本结构

  1. TI1FP1和TI2FP2分别对应定时器的CH1、CH2这两个引脚
  2. 输入捕获的前两个通道 通过GPIO口接入编码器的A、B相 然后通过滤波器和边沿检测极性选择  产生TI1FP1和TI2FP2 通向编码器接口 编码器接口通过预分频器控制CNT计数器的时钟 同时 编码器接口还根据编码器的旋转方向 控制CNT的计数方向 编码器正转时 CNT自增 编码器反转时 CNT自减

  3. 这里ARR是有效的 一般我们会设置ARR为65535(最大量程) 这样的话 利用补码的特性 很容易得到负数 比如CNT初始为0 正转 CNT自增,0、 1、2、3、4、5、6、7等等  反转时CNT自减 0下一个数就是65535 接着是65534 65533等等 这里负数不应该是-1、-2吗  所以直接把这个16位的无符号数转换为16位的有符号数 根据补码的定义 这个65535就对应-1 65534就对应-2(有符号编码时负数按补码计算,2^16 的补码= -1)等等 这样就可以直接得到负数 非常方便 这就是我们读出数据得到负数的一个小技巧

4.工作模式

5.实例

5.1 均不反相

  • 红框内就是正交编码器抗噪声原理 由图可知 TI2没有发生变化 但TI1却跳变好几次 这不符合正交编码器的信号规律 然后通过上表逻辑 成功将这种毛刺信号滤掉 TI1为上升沿 TI2为低电平 查表可知此时为向上计数 即自增 接着看下一个状态 TI1为下降沿 TI2为低电平 查表可知此时为向下计数 即自减 所以这里一个引脚不变 另一个引脚来回跳动 计数器会来回加、减、加、减 尽管发生多次变化 但其值与原先值还是一样

5.2 TI1反相

  • TI1反相的计数频率与5.1中的类似 只不过TI1真正的信号是与上图相反 如红色划线部分 后续也是如此 将其电位翻转后 通过查询表可知其计数方式

6.相关API

TIM_EncoderInterfaceConfig

void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);
功能:
	定时器编码器接口配置
参数:
    TIMx:其中x可以为1、2、3、4、5或8,选择TIM外设  
    TIM_EncoderMode: TIMx编码器模式
    TIM_IC1Polarity: IC1极性
    TIM_IC2Polarity: IC2极性
//参数3、4可以配置成TIM_ICPolarity_Falling: IC下降沿(反相)、TIM_ICPolarity_Rising: IC上升沿(不反相)
返回值:
	无    

7.编码器接口测速

7.1 实现思路

  1. 第一步,RCC开启时钟,开启GPIO和定时器的时钟
  2. 第二步,配置GPIO,这里需要把PA6和PA7配置成输入模式
  3. 第三步,配置时基单元,这里预分频器我们一般选择不分频,自动重装一般给最大65535,只需要个CNT执行计数就行了
  4. 第四步,配置输入捕获单元。不过这里输入捕获单元只有滤波器和极性这两个参数有用,后面的参数没有用到,与编码器无关
  5. 第五步,配置编码器接口模式。这个直接调用一个库函数就可以了

7.2 接线图

7.3 相关代码

Encoder.c
#include "stm32f10x.h"                  // Device header

void Encoder_Init(void)
{
    /*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
    /*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//将PA6引脚初始化为上拉输入
	//外部模块空闲默认输出高电平 选择上拉输入 默认输入高电平 外部模块空闲默认输出低电平 选择下拉输入 默认输入低电平 不过一般默认高电平 若不确定外部模块输出的默认状态或者外部模块输出功率非常小 这时就选择浮空输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;//这里TIM2要用来输出PWM 所以输入捕获的定时器需要换一个 暂时换到TIM3 由引脚定义表可以看到TIM3的通道1对应PA6 通道2对应PA7 通道3对应PB0 通道4对应PB1 这里选择TIM3的通道1 所以选择PA6引脚 这里需要配置上拉输入模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
    /*配置时钟源*/
//	TIM_InternalClockConfig(TIM3);//选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟
	//编码器接口是一个带方向控制的外部时钟 所以这个内部时钟就没用 
	
    /*时基单元初始化*/
	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;//预分频给0 就是不分频
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
	
    /*PWMI模式初始化*/
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);//该结构体最后两个参数在此无用处 因为这里只需配置滤波器和极性选择 但删除其他两个参数后可能显示结构体不完整 所以调用此函数给结构体赋一个初始值
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//配置通道参数 这里选择通道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;//配置通道参数 这里选择通道1
	TIM_ICInitStructure.TIM_ICFilter = 0xF;//用来配置输入捕获的滤波器 若信号有毛刺或噪声 可以增大滤波器参数 可以有效避免干扰
//	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//对应图里的边沿选择、极性选择部分
	TIM_ICInit(TIM3,&TIM_ICInitStructure);//将第二个结构体参数配置写入寄存器中 配置通道2
	
	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//编码器接口配置 第二个参数选择TI1和TI2都计数
	//这里第三个参数和第四个参数与上面的极性选择配置重复 其功能一样 后定义的函数会覆盖前面的 所以前面的可以注释掉

	TIM_Cmd(TIM3,ENABLE);
}

/**
  * 函    数:获取编码器的增量值
  * 参    数:无
  * 返 回 值:自上此调用此函数后,编码器的增量值
  */
int16_t Encoder_Get(void)
{
	/*使用Temp变量作为中继,目的是返回CNT后将其清零*/
	int16_t Temp;
	Temp = TIM_GetCounter(TIM3);
	TIM_SetCounter(TIM3, 0);
	return Temp;
}
Encoder.h
#ifndef __ENCODER_H
#define __ENCODER_H

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

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

int16_t Speed;//定义速度变量

int main(void)
{
	OLED_Init();//OLED初始化
	Timer_Init();//定时器初始化
	Encoder_Init();//编码器初始化
	
	OLED_ShowString(1,1,"Speed:");//1行1列显示字符串Speed:
	
	while (1)
	{
		OLED_ShowSignedNum(1,7,Speed,5);//不断刷新显示编码器测得的最新速度
	}
}

/**
  * 函    数:TIM2中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		Speed = Encoder_Get();								//每隔固定时间段读取一次编码器计数增量值,即为速度值
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}
}

现象:接上电源后OLED显示屏显示Speed:00000 旋转编码器 这里以顺时针转为正向 Speed的值会发生改变 旋转的越快数值越大 停止旋转则数值为0  逆时针旋转则为反方向 旋转越快数值越大 往负方向增大


注:若想改变旋转方向 即逆时针转为正向 顺时针转为反向

方法一:可以将A、B相接口接线互换位置

方法二:在Encoder.c的编码器配置函数中 第三个参数或者第四个参数选择反相即可 即一个选择Falling 另一个选择Rising 若两个选择一样则还是同向输出 类似于乘法(正正得正 正负得负 负负得正)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/368742.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux ln命令-linux软链接、硬链接-linux软、硬链接的区别(二):软链接

0、序 上一篇:linux ln命令-linux软链接、硬链接-linux软、硬链接的区别(一):硬链接 描述了硬链接相关内容,本篇主要描述软链接。 1、软链接 符号链接也称软链接,是将一个路径名链接到一个文件。这些文件是一种特别类型的文件。…

已解决!AttributeError: ‘Sequential‘ object has no attribute ‘session‘ 问题

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通Golang》…

【Android新版本兼容】onBackPressed()方法被弃用的解决方案

提示:此文章仅作为本人记录日常学习使用,若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、使用 AndroidX API 实现预测性返回手势1.1 添加依赖1.2 启用返回手势1.3 注册OnBackPressedCallback()方法来处理返回手势 一、使用 AndroidX API 实现预测…

React | Center 组件

在 Flutter 中有 Center 组件,效果就是让子组件整体居中,挺好用。 React 中虽然没有对应的组件,但是可以简单封装一个: index.less .container {display: flex;justify-content: center;align-items: center;align-content: ce…

京东微前端框架MicroApp简介

一、MicroApp 1.1 MicroApp简介 MicroApp是由京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度、提升工作效率。MicroApp无关技术栈,也不和业务绑定,可以用于任何前端框架。 官网链接:https://micro-zoe.gith…

Neo4j安装部署(windows、docker)

文章目录 Neo4j安装部署前言windows系统安装解压压缩包并进入bin目录查看neo4j的相关命令访问7474端口 Docker安装Neo desktop安装 Neo4j安装部署 前言 这篇blog所涉及的资源都可以在[neo4j相关资源]进行下载。 windows系统安装 解压压缩包并进入bin目录 查看neo4j的相关命…

正则表达式与文本处理工具

目录 引言 一、正则表达式基础 (一)字符匹配 1.基本字符 2.特殊字符 3.量词 4.边界匹配 (二)进阶用法 1.组与引用 2.选择 二、命令之-----grep (一)基础用法 (二)高级用…

FL Studio 21.2.2官方中文版重磅发布2024最新FL21下载安装图文使用教程

FL Studio 21.2.2中文版惯称水果编曲, 是一个完整的电音软件音乐制作环境或数字音频工作站。是现在流行的数字音频工作站之一,包括撰写,整理,记录,编辑,电音,混音和掌握专业品质的音乐。 FL Studio 21.2.2编曲软件即“Fruity Loops Studio”,简称FL,也就…

【C++初级篇】C++入门

目录 1. C关键字(C98) 2. 命名空间 2.1 命名空间定义 2.2 命名空间使用 3. C输入&输出 4. 缺省参数 4.1 缺省参数概念 4.2 缺省参数分类 5. 函数重载 5.1函数重载概念 5.2 C支持函数重载的原理--名字修饰(name Mangling) 6. 引用 6.1 引用概念 6.2 引用特性 6.3 常引用 6.4…

时间复杂度为 O(n) 的排序算法

大家好,我是 方圆。本文介绍线性排序,即时间复杂度为 O(n) 的排序算法,包括桶排序,计数排序和基数排序,它们都不是基于比较的排序算法,大家重点关注一下这些算法的适用场景。 桶排序 桶排序是分治策略的一…

内网信息收集-Windows篇

目录 内网信息收集 机器角色分析 本机的信息收集 密码信息 如何查找内网的网段 进程、端口、补丁、共享文件夹 总结 域环境信息收集 MSF信息收集 内网信息收集 机器角色分析 1、判断当前主机是什么服务器? web服务器、开发测试服务器、公共服务器、文件服…

[word] 怎么将word文档中的文字转换成一个4行5列的表格 #职场发展#笔记#经验分享

怎么将word文档中的文字转换成一个4行5列的表格 怎么将word文档中的文字转换成一个4行5列的表格? 将文档中的四行文字转换成一个4行5列的表格的具体步骤如下: 1、首先打开需要编辑的Word文档,进入到编辑页面中。 2、然后选中需要编辑的文字…

​Nacos搭建注册中心与配置中心

目录 一、Nacos的安装和部署 1. 下载Nacos 2. 解压安装包到本地 3. 配置数据库(可选) 4. 启动Nacos服务 5. 登陆控制台 二、springboot整合Nacos 1. 添加依赖 2. 配置注册中心、配置中心 3. 演示 Nacos是一个平台产品,主要提供注册…

《数据安全法》解读篇

《中华人民共和国数据安全法》 颁布时间:2021年6月10日实施时间:2021年9月1日《中华人民共和国数据安全法》整体架构图 数据安全的定义:是指通过采取必要措施,确保数据处于有效保护和合法利用的状态,以及具备保障持续…

使用ESP32-S3对MQ-135空气质量传感器的使用记录(Arduino版)

一、硬件上: 1、使用esp32开发板的04引脚与AO连接,检测AO引脚的电平 二、软件上: 1、使用Arduino快速完成开发 2、源码: // Potentiometer is connected to GPIO 04 (Analog ADC1_CH3) const int adcPin 4;// variable for s…

从零学习Linux操作系统 第二十五部分 文本处理工具

一、grep命令的基本使用方法及常用参数介绍 grep [全称&#xff1a;Globally search a Regular Expression and Print 全局搜索正则表达式并打印 ] grep 命令格式 grep 匹配条件 处理文件 grep root passwd过滤root关键字grep -i root passwd后略大小写grep -E “<root”…

鲜花销售|鲜花销售小程序|基于微信小程序的鲜花销售系统设计与实现(源码+数据库+文档)

鲜花销售小程序目录 目录 基于微信小程序的鲜花销售系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、前台功能模块 2、后台功能模块 (1) 后台登录 (2) 管理员功能模块 用户管理 商家管理 鲜花信息管理 鲜花分类管理 管理员管理 系统管理 (3) 商家功…

大数据时代效率革新:数字化管理助力企业迈向全新高度-亿发

在大数据时代的浪潮中&#xff0c;数字化管理成为企业不可或缺的发展趋势。以信息技术为支撑&#xff0c;数字化管理为企业带来了前所未有的机遇和挑战。让我们一起探讨&#xff0c;在这个数字时代&#xff0c;数字化管理如何引领企业走向更加高效、智能的未来。 1. 数据驱动决…

【Java程序设计】【C00243】基于Springboot的社区医院管理系统(有论文)

基于Springboot的社区医院管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的社区医院管理服务系统 本系统分为系统功能模块、管理员功能模块、用户功能模块以及医生功能模块。 系统功能模块&#xff1a;社…

Android Camera2 API 后台服务

最近在搞CameraAPP需要将Camera2弄成一个后台服务&#xff0c;发现跟预览的Activity没多大变动只是加了Service&#xff0c;和一些简单的修改。之前的公司也用到Camera2&#xff0c;发现用到的时候还是蛮多的所以记录一下&#xff0c;代码在文章末尾 camera2的结构如下&#x…