06:TIM定时器功能------编码器接口功能

目录

1:简历

2: 正交编码器

 3:编码器接口基本结构

 4:编码器的工作模式

5:极性反转

A:编码器接口测速

1:连接图

 2:函数介绍

3:步骤

4:代码

B:编码器接口计次

1:连接图

2:代码


1:简历

        Encoder Interface 编码器接口

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

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

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

2: 正交编码器

当编码器旋转起来的时候, 会输出下面的方波信号

 3:编码器接口基本结构

        编码器接口,都是上升沿和下降沿都有效的 , 上升沿和下降沿都需要计次 ,  所以在编码器接口模式下 ,  边沿检测极性选择就不再是边沿的极性选择了 ,  而是高低电平的极性选择.

        选择上升沿的参数------就是信号直通过来,高低电平极性不反转---5:极性反转

        选择上升沿的参数-------就是信号通过一个非门过来,高低电平极性反转----5:极性反转

        

 4:编码器的工作模式

         正转的状态都向上计数,   反转的状态都向下计数----TIM_EncoderMode_TI12

        上面的2个模式--只在一个计数

5:极性反转

均不反转

 TI1反转

 

A:编码器接口测速

1:连接图

 2:函数介绍

在stm32f10x tim.h文件中的函数------配置定时器编码器接口

void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
 

  TIM_EncoderInterfaceConfig  TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

参数 : 第二个参数---见上面的 4:编码器的工作模式

           第三个(IC1极性)和第四个(IC2极性)参数一样 : ----   3:编码器接口基本结构中的 边沿检测极性选择

        这里的上升沿并不代表上升沿有效 , 因为编码器接口始终都是上升沿、下降沿都有效的 , 这里的上升沿参数代表的是高低电平极性不反转-----5:极性反转

在stm32f10x tim.h文件中的函数------读取计数器CNT的值

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx)

TIM_SetCounter :计数器读取到了65535清零

在stm32f10x tim.h文件中的函数------给CNT重新赋值

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter)
 

TIM_SetCounter : 第二给参数: 读取CNT后,改它赋一个新的值;  我们这里选择把他清零

在stm32f10x tim.h文件中的函数------中断标志位和标志位清零

ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);

void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
 

TIM_GetITStatus: 获取中断标志位是否被置1了(检测外部中断的状态)

TIM_ClearITPendingBit清除中断挂起标志位

3:步骤

配置定时器编码器接口的步骤

1 : RCC开启时钟,(TIM外设---RCC_APB1PeriphClockCmd和GPIO外设----RCC_APB2PeriphClockCmd的时钟打开)

2 : 配置GPIO----GPIO_Init    (最后写第二步)

3 :  配置时基单元-----TIM_TimeBaseInit()

4 :  配置输入捕获(ic)----TIM_ICInit()--- IC需要配置2篇见代码

5 :   配置定时器编码器接口---TIM_EncoderInterfaceConfig()

6 : 启动定时器-----TIM_Cmd()

定时器开启步骤

1: 开启时钟 (RCC)

2: 选择时基单元的时钟 (TIM_InternalClockConfig--选择内部时钟)

3: 配置时基单元  (TIM_TimeBaseInit)

4 : 使能更新中断( TIM_ITConfig中断时钟控制)

5: NICV的配置   (见 02: STM32)

6: 启动定时器  (TIM_Cmd)

定时器开启步骤    详情见:03:TIM定时器

4:代码

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
#include "Delay.h"void Timer_init(void){
//第一步是开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//第二步,选择时基单元的时钟 (stm23上电默认使用的是内部时钟,这一行代码可以省略)
TIM_InternalClockConfig(TIM2);
//第三步,配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
/*计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1定时频率=72M/(PSC+1)/(ARR+1)72MHZ=72000KHZ72000KHZ/7200=10KHZ=10000HZT=1/F   T=1/10000hz=0.0001s=0.1ms然后以0.1ms的周期计10 000个数,所以就是1s*/
TIM_TimeBaseInitStructure.TIM_Period=10000-1;			//自动重装载寄存器ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;  //预分频器PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器特有的(重复寄存器)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//第四使能更新中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动清除更新中断标志位//第五步NICV的配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
//第六步启动定时器
TIM_Cmd(TIM2,ENABLE);
}void Encoder_Init(void)
{//1:配置RCC,把我们这里涉及的外设的时钟都打开(GPIO,AFIO)RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//2:配置GPIO,选择我们的端口为输入模式  注意打开了2个中断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(GPIOB, &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;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//配置输入捕获(IC)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_Cmd(TIM3, ENABLE);
}int16_t Encoder_Get(void)
{int16_t Temp;//读取CNT的值Temp = TIM_GetCounter(TIM3);TIM_SetCounter(TIM3, 0);return Temp;
}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);//Delay_ms(1000);}
}void TIM2_IRQHandler(){//检查中断标志位if (	TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){//清除标志位//Num++;Speed=Encoder_Get();TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}}

        只有TIM定时器的通道1和通道2接口可以作为 编码器接口

        通道3和通道4并不能做为编码器接口

IC需要配置2遍

B:编码器接口计次

        这个代码是通过定时器的编码器接口,来自动计次;  

        之前的代码是通过触发外部中断 , 然后在中断函数里手动进行计次-----见02:STM32--EXTI外部中断

1:连接图

2:代码

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
#include "Delay.h"void Encoder_Init(void)
{//1:配置RCC,把我们这里涉及的外设的时钟都打开(GPIO,AFIO)RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//2:配置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(GPIOB, &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;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//配置输入捕获(IC)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_Cmd(TIM3, ENABLE);
}int16_t Encoder_Get(void)
{return  TIM_GetCounter(TIM3);
}int main(void)
{OLED_Init();Encoder_Init();OLED_ShowString(1, 1, "Speed:");while (1){OLED_ShowSignedNum(1,7,Encoder_Get(),5);}
}

TIM篇章完结

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

变量函数及销毁函数中的变量-PHP8知识详解

今天分享php8知识详解中的变量函数及销毁函数中的变量,以及相应的示例代码。 1、变量函数 变量函数,是指通过变量来访问的函数。当变量后有圆括号时,PHP将自动寻找与变量的值同名的函数,然后执行该函数。 变量函数引用&#xf…

uniapp使用sqlite 数据库

uniapp使用sqlite 数据库 傻瓜式使用方式,按步骤,即可使用。 1.开启sqlite 在项目中manifest.json该文件中配置 2.封装数据库的调用方法 const sqlName "zmyalh" //定义的数据库名称 const sqlPath "_doc/zmyalh.db" //定义数…

如何通过人工智能和自动化提高供应链弹性?

全球供应链中的数字化转型已经引起了广泛关注,尽管在过去的十年中,这一话题被广泛讨论,但许多公司仍然对如何实现这一不明确的目标感到困惑。人们普遍认识到这种转变的重要性,而新冠疫情及其带来的巨大影响也为行业向数字化转型方…

【Go 基础篇】Go语言分支结构:掌握 if 和 switch,灵活控制程序逻辑

介绍 在编程中,分支结构是一种重要的控制流程,它允许程序根据不同的条件选择不同的执行路径。Go语言提供了两种主要的分支结构:if 和 switch,用于在程序中实现条件判断和多重选择。本篇博客将深入探讨Go语言中的if和switch分支结…

EureKa快速入门

EureKa快速入门 远程调用的问题 多个服务有多个端口,这样的话服务有多个,硬编码不太适合 eureKa的作用 将service的所有服务的端口全部记录下来 想要的话 直接从注册中心查询对于所有服务 每隔一段时间需要想eureKa发送请求 保证服务还存活 动手实践 …

后端开发有哪几种语言? - 易智编译EaseEditing

后端开发是构建应用程序的一部分,负责处理服务器端的逻辑、数据库交互和数据处理。有许多编程语言可用于后端开发,以下是一些常见的后端开发语言: Java: Java是一种广泛使用的面向对象编程语言,具有强大的跨平台能力。…

常见前端面试之VUE面试题汇总八

22. Vue 子组件和父组件执行顺序 加载渲染过程: 1.父组件 beforeCreate 2.父组件 created 3.父组件 beforeMount 4.子组件 beforeCreate 5.子组件 created 6.子组件 beforeMount 7.子组件 mounted 8.父组件 mounted 更新过程: 1. 父组件 befor…

Unity 之transform.LookAt() 调整一个物体的旋转,使其朝向指定的位置

文章目录 总的介绍补充(用于摄像机跟随的场景) 总的介绍 transform.LookAt 是 Unity 引擎中 Transform 组件的一个方法,用于调整一个物体的旋转,使其朝向指定的位置。通常情况下,它被用来使一个物体(如摄像…

cpolar做一个内网穿透

因为不在公司,需要访问公司的数据库,所以做一个内网穿透 下载安装 下载地址: https://dashboard.cpolar.com/get-started 下载后是个压缩包,解压后傻瓜式安装 操作隧道 安装后打开Cpolar Web UI 登录账号,查看隧…

Linux内核学习(九)—— 虚拟文件系统(基于Linux 2.6内核)

虚拟文件系统(VFS)作为内核子系统,为用户空间程序提供了文件和文件系统相关的接口。通过虚拟文件系统,程序可以利用标准的 Unix 系统调用对不同的文件系统(甚至不同介质上的文件系统)进行读写操作。 一、通…

分享几个 Selenium 自动化常用操作

最近工作会用到selenium来自动化操作一些重复的工作,那么在用selenium写代码的过程中,又顺手整理了一些常用的操作,分享给大家。 常用元素定位方法 虽然有关selenium定位元素的方法有很多种,但是对于没有深入学习,尤…

直播平台源码搭建协议讲解篇:传输控制协议TCP

简介: 由于直播平台在当今时代发展的越来越迅速,使得直播平台的技术功能越来越智能,让用户在直播平台中能够和其他用户进行实时互动,让用户可以获取到全世界最新的资讯,让一些用户可以作为主播获得工作,让…