STM32之TIM编码器接口

 

编码器简介:

 

例子讲解:正交编码器有两个输出,一个A相,一个B相,AB接口输出正交信号。然后接入STM32的定时器的编码器接口,编码器接口自动控制定时器时基单元中的CNT计数器进行自增或自减,比如初始化之后,CNT初始值为0,然后编码器右转,CNT就++,右转产生一个脉冲,CNT就加一次,比如右转产生10个脉冲(上升沿或者下降沿)之后,停下来,那么这个过程CNT就由0自增到10,停下来,编码器右=左转,CNT--,左转产生一个脉冲,CNT减一次,比如编码器再左转产生5个脉冲,那就在原来10的基础上自减5,停下来。
这个编码器接口,其实就相当于是一个带有方向控制的外部时钟,它同时控制这CNT的计数时钟和计数方向,这样的话,CNT的值就表示了编码器的位置,如果我们每隔一段时间取一次CNT的值,再把CNT清零,是不是每次取出来的值就表示了,编码器的速度,由上一篇笔记中的测频法和测周法的知识,这个编码器就是测频法测正交脉冲的频率,CNT计次然后每隔一段时间去一次计数值,只不过这个编码器接口更加高级,它能根据旋转方向,不仅可以自增计次,还可以自减计次,是一个带方向的测速
编码器接口资源比较紧张,如果一个定时器被配置成编码器接口模式,那它基本上就干不了其他的活了(如STM32F103C8T6只有4个定时器,所以最多只能接4个编码器),如果编码器不够用的话就要考虑一下资源够不够用,也可通过使用EXTI外部中断这就是用软件资源弥补硬件资源
每个定时器的CH3和CH4不能接编码器
 

正交编码器:

 

用正交信号的好处:

a、正交信号精度更高,因为A、B相都可以计次,相当关于计次频率提高了一倍

b、其次正交信号可以以抗噪声,因为正交信号两个信号必须是交替跳变的,可以设计一个抗噪声电路,如果一个信号不变,另一个信号连续跳变,也就是产生了噪声,这时计次值是不会变化的

编码器接口的设计逻辑:

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

 

编码器接口有使用CH1和CH2的输入捕获滤波器和边沿检测(高低电平是否反转,也就是TI,T2是否反相),编码器接口没有使用后面的是否交叉、预分频器、CCR寄存器与编码器接口无关

编码器接口的输出部分:相当于从模式控制器,去控制CNT的计数时钟和计数方向

注:在这里,我们并不会使用72M内部时钟和在时基单元初始化设置的计数方向,因为此时计数时钟和计数方向都处于编码器接口托管的状态,计数器的自增和自减手编码器控制

编码器接口基本结构示意图

 

 整体工作模式:

 

注:1、正转的状态都向上计数,反转的状态都向下计数

        2、一般选择第三个模式(在TI1和TI2上计数),精度高

 

实例讲解以及正交信号抗噪声原理:

TI1和TI2都不反向

 

TI1反相,TI2不反相(相当于把T1的信号取反再依据表格里的规则进行计数)

 若发现正转自减、反转自增,则应该把某个极性反相,就能反转计数方向,或者TI1\TI2调换

 

编码器接口测速实验


1、功能:每隔一段时间去计数值,就能得到编码器旋转的速度
        向右旋转:计数为正,想左旋转,计数为负,大小均为速度

        现在:通过定时器的编码器接口,自动计次(节约软件资源)

        之前:触发外部中断,在中断函数中自动计次

原理图:

 

步骤:

第一步:RCC开启时钟,开启GPIO和定时器的时钟

第二步:配置GPIO,PA6和PA7配置成输入模式

第三步:配置时基单元,预分频器选择不分频,自动重装,一般给最大65535,只需要给CNT执行计数即可

第四步:配置输入捕获单元(只有滤波器和极性两个参数)

第五步:配置编码器接口模式(调用库函数)

最后,调用TIM_Cmd开启定时器

电路初始化后,CNT会随着编码器旋转而自增自减
若想测量编码器的位置:直接读出CNT即可
测量编码器的速度和方向:需要每隔一段固定的闸门时间,取出一次CNT,然后再把CNT清零,这是测频法测量速度,需要用到定时器功能。


 

 

4、代码:

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
	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_ICPolarity = TIM_ICPolarity_Rising; //这里的上升沿不代表上升沿有效,仅仅代表高低电平极性不反转。
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //这里的上升沿不代表上升沿有效,仅仅代表高低电平极性不反转。
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	//编码器接口配置
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	//TIM_EncoderMode_TI12:根据TI1FP1和TI2FP2边的计数
	//TIM_ICPolarity_Rising:这里的上升沿不代表上升沿有效,仅仅代表高低电平极性不反转。Rising:极性不反转
	
	TIM_Cmd(TIM3, ENABLE);
}

int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = TIM_GetCounter(TIM3);  //读取计次值
	TIM_SetCounter(TIM3, 0);   //清零计次值
	return Temp;
}

 Timer.c(1秒触发一次中断)

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

/*
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

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();
	Timer_Init();
	Encoder_Init();
	
	OLED_ShowString(1, 1, "Speed:");
	
	while (1)
	{
		OLED_ShowSignedNum(1, 7, Speed, 5);
	}
}

void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		Speed = Encoder_Get();
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

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

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

相关文章

【笔记】C# 泛型约束

🗽 作者:哈桑c(CSDN平台) 🌠 专栏:全栈开发自学记录 文章目录什么是泛型约束?示例代码1、值类型约束(: struct)2、引用类型约束(: class)3、可为空…

基于springboot实现校园在线拍卖电商系统【源码】

基于springboot实现校园在线拍卖系统演示开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包&…

除了四大“门派”菌,一文了解肠道菌群的其它17个小众“门派”细菌

谷禾健康 以前我们科普过肠道菌群在门级别水平分类的肠道细菌四大常见菌门——拟杆菌门,厚壁菌门,变形菌门,放线菌门。 详见:肠道细菌四大“门派”——拟杆菌门,厚壁菌门,变形菌门,放线菌门 但是…

Java 线程调度

一、什么是线程调度 1.当同一时刻有多个线程处于可运行状态,它们需要排队等待CPU资源,每个线程会自动获得一个线程的优先级(Priority),优先级的高低反映线程的重要或紧急程度。 2.可运行的线程按优先级排队&am…

C语言的灵魂---指针(进阶)

C语言灵魂---指针(进阶)1.指针思维导图:2.字符指针3.数组指针与指针数组3.1指针数组3.2数组指针3.3 &数组名与数组名4.数组参数和指针参数4.1 一维数组传参4.2 二维数组传参4.3 一级指针和二级指针传参5.函数指针5.1 函数指针的定义5.2 函…

两数之和(力扣刷题)

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答…

Docker安装Redis集群(主从复制)

Docker安装Redis集群(主从复制) 部署Redis集群 配置阿里云镜像 sudo vim /etc/docker/daemon.json插入如下镜像 {"registry-mirrors": ["https://sdiz8d27.mirror.aliyuncs.com"] }重启docker sudo systemctl daemon-reloadsudo systemctl restart do…

如何利用ChatGPT自动生成SQL语句

作为一名开发者,你可能已经使用过自然语言处理(NLP)及其可能彻底改变我们与技术互动的方式。由OpenAI提供支持的文本到SQL工具是一种强大的方法,可以从自然语言文本中生成SQL语句。在本博客文章中,我们将探讨七个创造性…

物流云数据分析平台

物流云数据分析服务平台 http://project.webcats.cn/bx/36569/2455/index.html 本次系统模拟的是湖南省数据,解释权归杭氏集团所有! 1、系统简介: 物流大数据集成展示系统旨在通过大屏幕全面显示指定地区的物流运营车辆、物流公司和货主的相关信息和…

java版工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离 功能清单

ava版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下: 首页 工作台:待办工作、消息通知、预警信息,点击可进入相应的列表 项目进度图表:选择(总体或单个)项目显示1…

自由传奇|为你的队伍加油!

一个关于运动生活方式和如何将运动实践提升到新高度的独家 NFT 作品集。为你的队伍欢呼,认识传奇人物,以及每个球队的庆祝方式。 NFT 是自由传说游戏体验的一部分,在 The Sandbox 上独家推出。 该系列将于已在 The Sandbox 市场平台上线。 NF…

Mysql-索引-数据结构

Mysql索引-B树/B树 tip 索引好处初体验: select count(*) from ydl_user; -- 5.429 select * from ydl_user where user_id 1000000; -- 0.355s select * from ydl_user where user_name Jennifer Susan Johnson; -- 4.715s一方面mysql的数据是存储在磁盘上的&…

javaEE简单示例——基于注解的事务管理

简单介绍: 在之前,我们介绍了基于XML配置文件的配置方式,这种方式对于程序员来说还是比较繁琐了,我们这次来介绍一个更简单的方式来配置事务管理,那就是基于注解的事务管理。 接下来我们来开始介绍基于注解的事务管理…

轻松拿下年薪35W+Offer!这15个高频开发面试问题必须掌握!

作为SaaS行业的先驱,Salesforce的发展一路高歌猛进。Salesforce开发人员不仅能学习到最新的技术,而且比其他行业的同岗位享有更高的薪水,这也驱使了越来越多人加入Salesforce大军。 通过自由侠部落目前发布的岗位机会来看,即使在二…

企业邮箱的定义和要求

在讨论哪个企业邮箱最好使用之前,我们先明确一下企业邮箱的定义和要求? 以下是安全性、管理权限、员工体验、服务品质四个方面的总结,希望对您的选择有所帮助: 1.安全性 安全第一,这是不变的真理!当企业使…

vue-antd-admin——实现全网站选项的切换并实现页面的刷新——技能提升

今天写后台管理系统时,遇到一个需求,是关于内外贸选项的切换。 效果图如下: 默认是内贸选项,当进行切换时,无论是在哪个页面,当前页面都要进行刷新,并将选项的参数传递到接口中。 下面详细介…

iOS私有pod库的gitignore文件

我们在进行pod 死有库开发的时候,如果使用默认生成的gitignore 文件,每次提交和拉代码都会有大量的冲突,会严重干扰我们正常的开发,所以有必要进行设置一些忽略文件 通常pods 文件夹中的文件是要忽略的,还会有podfile…

聊一聊前端的性能指标

一、前端性能指标有哪些? 根据 chrome Lighthouse 最新规则,前端性能指标考量主要有 FCP(First Contenful Paint)、SI(Speed Index)、LCP(Largest Contentful Paint)、TBT&#xff…

CSS transition 小技巧!如何保留 hover 的状态

前言 通常情况下,hover 是无法保存状态的。鼠标移入触发额外样式,一旦移出就还原了 el:hover{color: red }这就意味着,如果需要保留 hover 的状态,可能就不得不借助 JS 了,比如下面是某某书院的首页排行榜效果。 这…

图解redis的AOF持久化

目录 1.引言 2.AOF持久化的实现 2.1命令追加 2.2AOF文件的写入 3.AOF的文件载入和数据还原 4.AOF重写 4.1AOF重写实现 4.2AOF后台重写(BGREWRITEAOF) 1.引言 redis是一个内存数据库,如果需要保存在磁盘那么就是需要持久化&#xff08…
最新文章