STM32——TIM输入捕获

news2024/11/22 10:18:09

文章目录

  • 一、TIM输入捕获
    • 输入捕获简介
    • 频率测量
  • 二、通用定时器的输入捕获通道
    • 通用定时器框图
    • 通道的输出部分
  • 三、主从触发模式
    • 主模式
    • 从模式
  • 四、输入捕获基本结构
  • 五、PWMI基本结构
  • 六、输入捕获模式测频率
    • 电路设计
    • 关键代码
  • 七、PWMI模式测频率占空比
    • 电路设计
    • 关键代码
  • 八、定时器库函数(tim.h)

一、TIM输入捕获

输入捕获简介

  • IC(Input Capture)输入捕获
  • 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔(频率)、电平持续时间(占空比)等参数
  • 每个高级定时器和通用定时器都拥有4个输入捕获通道
  • 可配置为PWMI模式,同时测量频率和占空比
  • 可配合主从触发模式,实现硬件全自动测量
  • 对于同一个定时器,由于其通道引脚是共用的,输入捕获和输出比较只能使用其中一个
  • 输入捕获的功能和外部中断类似,但是在外部中断中,引脚出现指定电平跳变的时候是向CPU申请中断,而输入捕获是将CNT锁存在CCR中,而不是进行比较

频率测量

在这里插入图片描述

  • 测频法:在闸门时间T内【一般是1s】,对上升沿计次【一个上升沿就是一个周期】,得到N,则频率【适合高频】
    在这里插入图片描述

  • 测周法(利用周期的倒数是频率):两个上升沿内,以标准频率fc计次【通过已知频率求】,得到N ,则频率【适合低频】
    在这里插入图片描述

  • 中界频率:测频法与测周法误差相等的频率点【设N相同求解】,大于中界频率选测频法,小于中界频率选测周法。因为N越大,+1/1误差对频率的影响越小
    在这里插入图片描述

二、通用定时器的输入捕获通道

通用定时器框图

在这里插入图片描述

  • CH1/2/3三个引脚接到异或门,只要有一个引脚电平翻转就触发一次电平翻转。该设计是为三相无刷电机服务,三个霍尔传感器检测转子的位置
  • TI1左边是数据选择器,可以选择是异或通道输出还是各个通道各自输出
  • 输入滤波器和边沿检测器:有两套滤波和边沿检测,分别输出TI1FP1和TI2FP2
  • IC1和IC2旁边的数据选择器负责交换连接:1. 灵活切换后续输入捕获电路的输入。2. 一个引脚的输入映射到两个捕获单元,也就是PWMI模式,两个通道同时对一个引脚捕获,测量占空比和频率
  • 预分频器:每来一个上升沿,将CNT存在CCR中,用于计数计时(内部时钟源可以计算时间)同时还可以触发捕获中断

通道的输出部分

在这里插入图片描述

  • 从TI1F_ED通道或TI1FP1通道到从模式:有硬件电路可以自动完成CNT清零,
  • IC1PS通道:手动完成CNT清零

IC1F寄存器:

在这里插入图片描述

  • 滤波器:采样频率越低,采样个数N越大,滤波效果越好

三、主从触发模式

主模式

在这里插入图片描述

  • 将定时器内部信号映射到TRGO引脚
  • 接收其他外设信号或自身外设的信号,用于控制自身定时器的运行
  • 主模式选择
    在这里插入图片描述

从模式

在这里插入图片描述

  • 如图所示,通道3和4没有触发源可以选择,但可以通过触发捕获中断,在中断函数中手动清零CNT,容易消耗软件资源,不断进入中断

  • 触发源选择
    在这里插入图片描述

  • 从模式选择
    在这里插入图片描述

  • TIM输入捕获采用从模式:触发源选择TI1FP1,从模式中选择Reset

    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//选择输入触发源TRGI
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//选择从模式
    

四、输入捕获基本结构

在这里插入图片描述

  • 从模式只有通道1和通道2,通道3和4只能通过在捕获中断函数里面清除CNT的值

  • 采用测周法,需要知道标准频率fc和计次N,fc就等于CNT的驱动时钟即预分频的值
    在这里插入图片描述

  • 每次捕获完成都需要将CNT的值清零,可以用主从触发模式完成

设置为输入捕获通道需要配置成浮空输入

在这里插入图片描述

五、PWMI基本结构

在这里插入图片描述

  • CCR2捕获并不会触发CNT清零,此时高电平的计数值存放在CCR2里面

  • CCR2/CCR1=占空比

  • 函数

    TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//该函数只需要传入一个通道即可,会默认将另一个通道取反配置
    

六、输入捕获模式测频率

电路设计

在这里插入图片描述

  • PA0通过输出比较电路输出PWM波,PA6为输入捕获通道

关键代码

IC.c

#include "stm32f10x.h"                  // Device header

void IC_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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	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 = 72 - 1;		//PSC,计数器自增频率=fc=72MHZ/(PSC+1)
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//输入捕获通道
	TIM_ICInitStructure.TIM_ICFilter = 0xF;//滤波器
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性选择
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//直连还是交叉连接
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//主模式触发源
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//从模式配置为RESET
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
	//TIM_GetCapture1/2/3/4()获取输入捕获模式下CCR寄存器的值
}

  • 由于输出比较通道使用TIM2,而捕获/比较寄存器是不能共用的,所以输入捕获通道采用TIM3

PWM.c

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	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 = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}
//调节PWM占空比,当ARR为100-1时,CCR就是占空比
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);
}
//调节PWM频率,由于频率收到ARR和PSC影响,修改ARR还会影响到占空比,此处只修改PSC的值
void PWM_SetPrescaler(uint16_t Prescaler)
{
	TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
	//第三个参数指定预分频器的重装模式:可以选立即生效和更新事件后生效
}

main.c

修改预分频,观察输入捕获测量的频率

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

int main(void)
{
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1, 1, "Freq:00000Hz");
	
	PWM_SetPrescaler(720 - 1);			//Freq = 72M / (PSC + 1) / 100
	PWM_SetCompare1(50);				//Duty = CCR / 100
	
	while (1)
	{
		OLED_ShowNum(1, 6, IC_GetFreq(), 5);
	}
}

七、PWMI模式测频率占空比

电路设计

在这里插入图片描述

  • PA0通过输出比较电路输出PWM波,PA6为输入捕获通道

关键代码

IC.c

#include "stm32f10x.h"                  // Device header

void IC_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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	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 = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//快速配置两个通道

	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
//获取占空比=CCR2/CCR1
uint32_t IC_GetDuty(void)
{
	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}

八、定时器库函数(tim.h)

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);//输入捕获通道初始化,四个通道占用一个函数,在结构体中可以选定通道
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);//快速配置两个通道,用于PWMI模式
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);//结构体初始化
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);//选择输入触发源TRGI
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);//选择输出触发源TRGO
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);//选择从模式
//分别配置通道的分频器
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);
//分别读取四个通道的CCR值
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分而治之——图的连通性问题及板子

连通性的判断 两大算法:并查集 和 图的遍历(DFS BFS) 分而治之的题目与解答 在这道题的下面 3587. 连通图 - AcWing题库 连通性的判断 两种方法 1.这里连通性的判断是判断连通分支是否包含所有的点。 2.也可以不开cnt数组,直接…

【算法】贪心算法(第四章习题解答)

4 贪心算法 4.1 若在 0−10-10−1 背包问题中, 各物品依重量递增排列时, 其价值恰好依递减序排列. 对于这个特殊的 0−10-10−1 背包问题, 设计一个有效算法找出最优解, 并说明算法的正确性. 算法设计:由题目所给的信息可以知道这种特殊的背包问题可以通过贪心算法…

基于多保真方法来估计方差和全局敏感度指数分析(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 此代码实现了多保真方法来估计方差和全局敏感度指数。当模型具有不确定的输入时,模型输出也是不确定的。基于方差的…

C++与QML混合编程

一、前言 简单来说,混合编程就是通过Qml高效便捷的构建UI界面,而使用C 来实现业务逻辑和复杂算法。Qt集成了QML引擎和Qt元对象系统,使得QML很容易从C 中得到扩展,在一定的条件下,QML就可以访问QObject派生类的成员&am…

112.(leaflet之家)leaflet椭圆修改

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> <html>

OpenHarmony之轻量系统编译构建流程

首先我们先来熟悉几个概念&#xff1a; - 子系统 子系统是一个逻辑概念&#xff0c;它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计&#xff0c;从下向上依次为&#xff1a;内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级…

别人家的公司年终奖52个月工资-互联网企业年终裁员脸在哪

52个月工资&#xff0c;开玩笑吧&#xff0c;还真不是。据台湾媒体报道&#xff0c;中国台湾长荣海运年终奖出炉&#xff0c;继去年40个月年终奖后&#xff0c;今年再创新高&#xff0c;传言最高发放52个月年终奖金。以基层员工月薪5万新台币计算&#xff0c;表现好的员工可领到…

6.vector、set和map

一、vector 1.简介 有些时候想开一个数组&#xff0c;但是却不知道应该开多大长度的数组合适&#xff0c;因为我们需要用到的数组可能会根据情况变动。这时候我们就需要用到动态数组。 所谓动态数组&#xff0c;也就是不定长数组&#xff0c;数组的长度是可以根据我们的需要…

第四章快速排序——分而治之

分而治之&#xff08;divide and conquer,D&C&#xff09; D&C算法是递归的&#xff0c;并且有2个步骤&#xff1a; 找出基线条件&#xff0c;并且条件尽可能简单不断将问题分解&#xff0c;直到符合基线条件 给定一个数组&#xff0c;求和&#xff1a; 利用循环很容…

秒懂双向链表

目录 一、双向链表概述 二、模拟实现双向链表 1、头插法插入元素 2、尾插法插入元素 3、在指定位置插入元素 4、查询双向链表中是否包含key 5、删除第一次出现关键字为key的结点 6、删除所有值为key的结点 7、求双向链表的长度 8、遍历双向链表 9、清空双向链表 三…

【 uniapp - 黑马优购 | 商品列表 】如何实现数据获取、结构渲染、自定义组件的封装

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;讨厌编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc…

在 Mac 上将 PDF 转换为 Word 的 5 种简单方法

当谈到将PDF格式转换为Word格式时&#xff0c;用户可能会从互联网上搜索并尝试在线将PDF转换为Word。如果是这样&#xff0c;您可能会得到不好的结果并冒着文件本身的风险。在线 PDF 到 Word 转换器工具可能会产生低质量的输出&#xff0c;对文件大小有限制&#xff0c;更糟糕的…

maven多模块依赖版本不一致问题

项目结构&#xff1a; ├─springcloud-alibaba ├─.idea├─shop-common├─shop-order├─shop-product└─shop-user项目环境&#xff1a; 父工程&#xff1a; <properties><spring-cloud.version>Greenwich.RELEASE</spring-cloud.version><sprin…

java虚拟机之垃圾回收机制

一.需要回收的内存区域 程序计数器、虚拟机栈、本地方法栈 3 个区域随线程生灭(因为是线程私有)&#xff0c;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。而 Java 堆和方法区则不一样&#xff0c;一个接口中的多个实现类需要的内存可能不一样&#xff0c…

<Focal Loss for Dense Object Detection>论文解读

目录1.简介2.模型2.1 二阶段要比单阶段模型效果好本质原因2.2 模型结构2.3.focal loss2.3.1 公式说明2.3.2 其他2.4 消融实验3.源码详解1.简介 目标识别有两大经典结构: 第一类是以Faster RCNN为代表的二阶段识别方法&#xff0c;这种结构的第一阶段专注于proposal的提取&am…

后端开发规约

目录 项目MVC层级设计规范 工程项目模块设计 设计规约 Java编码规范 参考《阿里巴巴Java开发手册》&#xff0c;见文末参考文档 OOP 面向对象设计 & 面向接口编程 Lombok工具包依赖 Guava、Hutool 等脚手架工具包&#xff08;三方包使用其一即可&#xff09; 日志打…

python初级教程十 Mongodb增、删、改、查

Mongodb 插入文档 MongoDB 中的一个文档类似 SQL 表中的一条记录。 插入集合 集合中插入文档使用 insert_one() 方法&#xff0c;该方法的第一参数是字典 name > value 对。 以下实例向 sites 集合中插入文档&#xff1a; #!/usr/bin/python3import pymongomyclient p…

03、Java并发 Java 线程池 ( Thread Pool ) (上)

本文我们将讲解 Java 中的线程池 ( Thread Pool )&#xff0c;从 Java 标准库中的线程池的不同实现开始&#xff0c;到 Google 开发的 Guava 库的前世今生。 本章节涉及到很多前几个章节中阐述的知识点。我们希望你是按照顺序阅读下来的&#xff0c;不然有些知识会一头雾水。 J…

Redis基础篇——Redis安装以及配置文件的修改

文章目录1. 认识Redis1.1 特征1.2 安装 Redis1. 安装 Redis 依赖2. 上传安装包1.3 默认启动1.4 指定配置启动1.5 开机自启&#xff08;推荐&#xff09;1. 认识Redis Redis 诞生于 2009 年&#xff0c;全称是 Remote Dictionary Server&#xff0c;远程词典服务器&#xff0c;…

Databend 开源周报 #73

Databend 是一款强大的云数仓。专为弹性和高效设计&#xff0c;自由且开源。 即刻体验云服务&#xff1a;https://app.databend.com。 What’s New 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 Features & Improvements Multiple Catalogs …