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

2023-11-11

目录

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=72000KHZ
	72000KHZ/7200=10KHZ=10000HZ
	T=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;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC
	TIM_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;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC
	TIM_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篇章完结

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

06:TIM定时器功能------编码器接口功能 的相关文章

  • KVM和QEMU

    原文地址 KVM和QEMU 作者 embeddedlwp 目录 1 硬件虚拟化技术背景 2 KVM的内部实现概述 2 1 KVM的抽象对象 2 2 KVM的vcpu 2 3 KVM的IO虚拟化 2 3 1 IO的虚拟化 2 3 2 Virt
  • jdk1.8.191 JVM内存参数 InitialRAMPercentage和MinRAMPercentage

    MaxRAMPercentage InitialRAMPercentage MinRAMPercentage 这三个参数是JDK8U191为适配Docker容器新增的几个参数 类比Xmx Xms 至于 XX InitialRAMFracti

随机推荐

  • 物联网安全概述

    什么是物联网 在你学习有关IPv6的时候 你的老师或许说过 有一天在你的房子每个设备都会有一个IP 物联网基本上就是处理每天的事务 并把它们连接到互联网上 一些常见的物联网设备 如灯光 窗帘 空调 也有像冰箱这样的不太常见的设备 甚至一个卫
  • [sicily] 1003. 相连的1

    声明 原题目转载自中山大学sicily平台 解答部分为原创 Problem 对于一个01矩阵A 求其中有多少片连成一片的1 每个1可以和上下左右的1相连 请为下面的Solution类实现解决这一问题的函数countConnectedOnes
  • 聚合支付行业术语,你get到了吗?

    俗话说 内行看门道外行凑热闹 每一个行业都有它独特的专业术语 对于外行人来说 这些专业术语就跟专有名词一样难懂 支付行业也是一样 因为是近几年的新兴行业 很多人对这一行不懂 甚至一些在支付行业工作的人 对这一行的很多名词概念也很模糊 认知仅
  • 基础篇(二):内存屏障是什么

    目录 前置知识 内存屏障 什么是内存屏障 作用 内存屏障的分类 1 强制读取 刷新主内存的屏障 强制刷新主内存 Load屏障 强制读取主内存 Store屏障 总结 2 禁止指令重排序的屏障 LoadLoad屏障 StoreStore屏障 L
  • 怎么修改游戏内存服务器,修改游戏服务器内存

    修改游戏服务器内存 内容精选 换一换 当您成功创建私有镜像后 镜像的状态为 正常 您可以使用该镜像创建服务器实例或云硬盘 也可以将镜像共享给其他帐号 或者复制镜像到其他区域 私有镜像的生命周期如图1所示 通过华为云创建的ECS服务器默认使用
  • mysql客户端小海豚_MySQL基础

    1 数据库概述 1 1数据的存储方式 第一种存储方式是创建对象 实际上new出来的对象不就是用来存数据的嘛 创建对象就是在堆内存中为对象请求了一个空间 相当于是将对象存入堆内存 第二种方式存文件中 这个在IO流部分我们就是这么处理的 但是缺
  • Python批量改文件名

    对以下路径中的文件名批量修改 文章目录 一 读取指定路径中的文件名 二 正则表达式提取需要保留的部分 1 介绍re库 2 re库中函数的用法 1 re findall 最常用 2 re sub pattern repl string cou
  • 数仓知识点

    传统数仓知识 1 数据仓库分层 ODS 数据准备层 该区为数据仓的准备区 直接输入源数据 如业务库 埋点日志和消息队列等 DWD 数据细节层 该层为业务层和数据层的隔离层 保持和ODS层相同的颗粒度 该层还进行了数据清洗和规范化操作 例如去
  • 阿里巴巴笔试-2020.7.27-第二题 藏宝架

    题目 有个藏宝架有n层 每层的宝物数量不一 每个宝物都有其价值 现在要求拿出m个宝物 并且需要遵守规则 每次只能拿选定层的两端的宝物 要拿出的m个宝物的总价值是各种方案里最大的 输入 第一行是 n 和 m 后面每一行是各层的数据 n m 下
  • WebSocket 基于JAVA Spring boot Spring Colud 的使用

    先上代码再看调试结果 package com qiang user util import com alibaba fastjson JSONObject import org springframework stereotype Comp
  • 软考网络工程师-最新最全小白攻略

    一 前言 最近Beau 博主本人 也是考取了2023年上半年的软考网络工程师 这里也准备给小白们做一些避坑流程 这里附上通过图 二 考前准备 1 报考条件 无 无年龄 资质 学历限制 无需通过软考初级才能报考 是中国守法公民即可报名 2 考
  • webpack 保存文件后自动打包_自动打包插件webpack-dev-server的安装、配置及使用

    1 介绍 webpack dev server插件可以实现Webpack的自动打包编译 这样 就不需要每次修改完代码都重新手动输入webpack打包了 2 安装 在项目的根路径下输入 cnpm i webpack dev server D
  • Python----模块(Module)和包(Package)

    Python 包 包 定义 为了组织好模块 会将多个模块分为包 Python 处理包也是相当方便的 简单来说 包就是文件夹 但该文件夹下必须存在 init py 文件 常见的包结构如下 最简单的情况下 只需要一个空的 init py 文件即
  • uniapp中使用网页录音并上传声音文件(发语音)——js-audio-recorder的使用【伸手党福利】

    uniapp中上传音频只能在app或小程序当中实现 如何使用网页完成语音的录制和上传则成为了困扰前端童鞋的重点 本文着重解决 js audio recorder报 error 浏览器不支持getUserMedia 的问题 js audio
  • qt使用socket连续发图片,服务端使用qt或者python接受图片

    首先客户端是用qt 不能用python这种 首先在pro里面 QT network 然后引入头文件 include
  • 2023最新AI创作商用ChatGPT源码分享+支持AI绘画

    一 SparkAI智能创作系统 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统 本期针对源码系统整体测试下来非常完美 可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统 那么如何搭建部
  • Vue 中使用 Upload 组件上传 Excel

    vue 中使用 Element 的 upload 组件上传 Excel 大致可以分两种情况 使用 action 上传到服务器 使用 axios 上传到服务器 注意 上传文件可能由于前后端格式不统一导致上传失败 application x w
  • openTLD算法在opencv3的PatchGenerator

    由于opencv3的各种版本相对于opencv2的版本已经改变了很多内容 openTLD跟踪算法所依赖的一些函数在opencv3中已经消失了 为此需要对openTLD进行适当修改才能使之在opencv3的各种版本中运行 加入如下文件 并在对
  • C++一本通基础算法:深度优先搜索(DFS)

    算法概述 搜索 类似于枚举 从头结点开始 搜索发现有一些路可以走 先选择一条 走到一个结点处 重复上述过程 一直走到不能走为止 然后返回上一个结点 选择第二条路 一直检索知道将头结点所有的路走完 算法图像 如图所示 从1开始 发现可以到达2
  • 06:TIM定时器功能------编码器接口功能

    目录 1 简历 2 正交编码器 3 编码器接口基本结构 4 编码器的工作模式 5 极性反转 A 编码器接口测速 1 连接图 2 函数介绍 3 步骤 4 代码 B 编码器接口计次 1 连接图 2 代码 1 简历 Encoder Interfa