TIM输入捕获-STM32

news/2024/7/5 9:38:19

TIM输入捕获-STM32

IC(Input Capture) 输入捕获
输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
每个高级定时器和通用定时器都拥有4个输入捕获通道可配置为PWMI模式,同时测量频率和占空比可配合主从触发模式,实现硬件全自动测量
在这里插入图片描述
输出比较和输入捕获的区别:
输出比较,引脚是输出端口;输入捕获,引脚是输入端口。
输出比较,是根据CNT和CCR的大小关系来执行输出动作;输入捕获,是接收到输入信号,执行CNT锁存到CCR的动作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一般我们可以根据分辨率的要求,先确定好ARR;比如分辨率,1%就足够了,那ARR给100-1,这样PSC决定频率,CCR决定占空比。
在这里插入图片描述
第一步,RCC开启时钟,把GPIO和TIM的时钟打开
第二步,GPIO初始化,把GPIO配置成输入模式,一般选择上拉输入或者浮空输入模式
第三步,配置时基单元,让CNT计数器在内部时钟的驱动下自增运行
第四步,配置输入捕获单元。包括滤波器、极性、直连通道还是交又通道、分频器这些参数;用一个结构体就可以统一进行配置了
第五步,选择从模式的触发源。触发源选择为TI1FP1,这里调用一个库函数,给一个参数就行了
第六步,选择触发之后执行的操作。执行Reset操作,这里也是调用一个库函数就行了
调用TIM_Cmd函数,开启定时器。

当我们需要读取最新一个周期的频率时,直接读取CCR寄存器,然后按照fc/N,计算一下就行了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试频率

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//第一步开启时钟,初始化RCC,选择TIM2
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);	
	//设置输出PWM的GPIO端口
		//使能GPIOA的时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	//GPIOA模式初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
		
	//第二步选择时基单元的时钟,选择内部时钟,选择TIM2
	TIM_InternalClockConfig(TIM3);
	
	//第三步配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数 1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数的模式 向上计数
	//频率为1KHz,占空比为50%的PWM波形
	//计数器溢出频率:CK CNT_OV = CKCNT /(ARR + 1)= CK PSC /(PSC + 1)/(ARR +1)
	//配置定时为1s,则CK CNT_OV=1;CKCNT=72MHz=72000000;
	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//周期,ARR自动重装器的值 范围0~65536 设置为最大值,防止溢出
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//PSC预分频器的值 范围0~65536 最后1Mhz
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器的值 高级计数器才有
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//第四步,配置输入捕获单元。包括滤波器、极性、直连通道还是交又通道、分频器这些参数
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//选择通道 选择TIM3的通道1
	TIM_ICInitStruct.TIM_ICFilter = 0xF;//用来配置输入捕获的滤波器。数越大滤波效果越好
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿触发
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置分频器,不分频
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//配置数据选择器,直连通道
	TIM_ICInit(TIM3,&TIM_ICInitStruct);
	
	//第五步,选择从模式的触发源。触发源选择为TI1FP1,这里调用一个库函数,给一个参数就行了
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	//第六步,选择触发之后执行的操作。执行Reset操作,这里也是调用一个库函数就行了
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//调用TIM_Cmd函数,开启定时器
	TIM_Cmd(TIM3,ENABLE);
}

//函数返回的是最新"个周期的频率值,单位是Hz
//Freq = CK_PSC / (PSC + 1) / (ARR + 1) 
//CK_PSC= 72MHz    PSC + 1 =100
uint32_t IC_GetFreq(void)
{
	return 10000000/(TIM_GetCapture1(TIM3)+1);
}

在这里插入图片描述

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//第一步开启时钟,初始化RCC,选择TIM2
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);	
	//设置输出PWM的GPIO端口
		//使能GPIOA的时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	//GPIOA模式初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
		
	//第二步选择时基单元的时钟,选择内部时钟,选择TIM2
	TIM_InternalClockConfig(TIM3);
	
	//第三步配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数 1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数的模式 向上计数
	//频率为1KHz,占空比为50%的PWM波形
	//计数器溢出频率:CK CNT_OV = CKCNT /(ARR + 1)= CK PSC /(PSC + 1)/(ARR +1)
	//配置定时为1s,则CK CNT_OV=1;CKCNT=72MHz=72000000;
	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//周期,ARR自动重装器的值 范围0~65536 设置为最大值,防止溢出
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//PSC预分频器的值 范围0~65536 最后1Mhz
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器的值 高级计数器才有
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//第四步,配置输入捕获单元。包括滤波器、极性、直连通道还是交又通道、分频器这些参数
	TIM_ICInitTypeDef TIM_ICInitStruct;
	
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//选择通道 选择TIM3的通道1
	TIM_ICInitStruct.TIM_ICFilter = 0xF;//用来配置输入捕获的滤波器。数越大滤波效果越好
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿触发
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置分频器,不分频
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//配置数据选择器,直连通道
	TIM_ICInit(TIM3,&TIM_ICInitStruct);
	TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);//在函数里,会自动把剩下的一个通道初始化成相反的配置
//	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;//选择通道 选择TIM3的通道1
//	TIM_ICInitStruct.TIM_ICFilter = 0xF;//用来配置输入捕获的滤波器。数越大滤波效果越好
//	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;//上升沿触发
//	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置分频器,不分频
//	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;//配置数据选择器,交叉输入
//	TIM_ICInit(TIM3,&TIM_ICInitStruct);
	
	//第五步,选择从模式的触发源。触发源选择为TI1FP1,这里调用一个库函数,给一个参数就行了
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	//第六步,选择触发之后执行的操作。执行Reset操作,这里也是调用一个库函数就行了
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//调用TIM_Cmd函数,开启定时器
	TIM_Cmd(TIM3,ENABLE);
}

//函数返回的是最新"个周期的频率值,单位是Hz
//Freq = CK_PSC / (PSC + 1) / (ARR + 1) 
//CK_PSC= 72MHz    PSC + 1 =100
uint32_t IC_GetFreq(void)
{
	return 10000000/(TIM_GetCapture1(TIM3)+1);
}

//获取占空比
//Duty = CCR / (ARR + 1)
uint32_t IC_GetDuty(void)
{
	//高电平的计数值存在CCR2里;整个周期的计数值存在CCR1里;用CCR2/CCR1,就能得到占空比了
	return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);//范围是0%~100%
}


http://lihuaxi.xjx100.cn/news/1117202.html

相关文章

第8章 函数探幽

1. 引用的本质 int a 1; int& copy a; //实际是:指针常量 int* const copy &a; 引用一旦指定后,就不能再作为其他变量的引用 2. 关于const和引用 非引用--无返回||引用-无返回类似 //1.可行 void test(int a); int a 1; test(a);//2.可行…

开关电源基础07:离线式开关电源变压器设计(1)

说在开头:关于第六届索尔维会议(2) 爱因斯坦一天都挺开心的,反正难题出给了玻尔,他还在自己的房间里拉起了小提琴,有人说爱因斯坦小提琴拉的跟锯木头一样,那也不至于那么夸张,但是水…

【算法】Smallest Integer Divisible by K 可被 K 整除的最小整数

文章目录 Smallest Integer Divisible by K 可被 K 整除的最小整数问题描述:分析代码 Tag Smallest Integer Divisible by K 可被 K 整除的最小整数 问题描述: 问题 给定正整数 k ,你需要找出可以被 k 整除的、仅包含数字 1 的【最小正整数…

杂记 2023.5.10

目录 韦伯和斯托亚科维奇是谁? 介绍一下kali FastDFS和Sentinel是什么? Inferno 找工作的影响因素 1. 背景: 2. 学习过程: 2.1 计算机基础: 2.2 语言: 2.3 数据库等: 2.4 JVM&#…

CCFCSP 201409-2 画图

思路上很容易想到即使用一个标记数组对上过色的模块进行标记&#xff0c;最后遍历该数组得到被标记的模块数即可 #include<iostream>using namespace std;int mapp[105][105]; int ans0;int main(){int n;cin>>n;for(int i0;i<n;i){int x1,y1,x2,y2;cin>>…

JavaScript经典教程(七)-- JavaScript初级

190&#xff1a;JavaScript初级内容 - DOM查询、插入内容、赋予样式等 1、DOM操作 DOM&#xff1a;节点&#xff0c;也就是html中的元素&#xff1b; DOM操作&#xff1a;其实就是节点元素的方法&#xff1b; &#xff08;1&#xff09;innerHTML - 返回元素内容 同时也可以…

表达式求值问题-双栈模板化实现

好久不见&#xff0c;真的很久都没有更新博客了&#xff0c;最近很多事情&#xff0c;所以比较忙碌&#xff0c;没有时间每天都学算法&#xff0c;但是我会挤时间尽量做到&#xff0c;每两三天就更新博客&#xff0c;我会努力的&#xff0c;加油~ 前言&#xff1a;计算器都见过…

SpringBoot基础篇1(搭建环境+基础配置)

一、SpingBoot入门案例 SpringBoot是用来简化Spring应用的初始搭建以及开发过程。 先快速搭建一个SpringBoot&#xff1a; 创建一个空project&#xff0c;再创建SpringBoot模块。 点击Create&#xff0c;出现以下页面配置成功 创建一个控制器测试一下&#xff1a; RestCo…