STM32定时器四大功能之输入捕获

本文详细介绍了STM32F10x平台中TIM3定时器的输入捕获功能,包括其工作原理、配置步骤、频率和占空比测量方法,以及主从触发模式的应用。
摘要由CSDN通过智能技术生成

1.输入捕获介绍

输入捕获可以用来测频率,同时也可以从来测占空比,输入捕获时是指引脚发生指定电平跳变时,当前的CNT锁存到CCR中。

可配置PWMI模式,同时测量频率和占空比。同时也可以配合主从触发模式,实现硬件的全自动

每个高级定时器和通用定时器都拥有4个输入捕获通道

 (1)输入捕获就是这左边一部分电路 那右边就是我们之前讲过的输出比较部分 四个输入捕获和输出比较通道 共用四个CCR寄存器 另外它们的CH1到CH4 4个通道的引脚也是共用的 所以对于同一个定时器输入捕获和输出比较 只能使用其中一个不能同时使用

(2)输入信号来到了输入滤波器和边沿检测器(极性选择) 输入滤波器可以对信号进行滤波 避免一些高频的毛刺信号误触发 边缘检测器可以选择上升沿触发或者下降沿触发 当出现指定的电平时 边沿检测电路就会触发后续电路执行动作

(3)这里设计了两套滤波和边沿检测电路 第一套电路经过滤波和极性选择得到TI1FP1 输入给通道1的后续电路 第二套电路 经过另一个滤波和极性选择 得到TI1FP2 输入给通道2的后续电路 同理 下面TI2信号进来 也经过两套滤波和极性选择得到TI2FP1输入通道1和TI2FP2输入通道2

其中TI1FP1输入给通道1的后续电路 TI1FP2 给通道2的后续电路也可以选择进行一个交叉 这样进行交叉连接。交叉的主要目的 就是可以把一个引脚的输入同时映射到两个捕获单元 这也是PWMI模式的经典结构

(4)输入信号进行滤波和极性选择后就来到了预分频器 每个通道各有一个预分频器 可以选择对前面的信号进行分频 分频之后的触发信号 就可以触发捕获电路进行工作了 每来一个触发信号 CNT的值就会向CCR转运一次 转运的同时会发生一个捕获事件。CNT计数器是由内部的标准时钟驱动的 所以CNT的数值可以用来记录两个上升沿之间的时间间隔(周期) 再取倒数就是测周法测量的频率了 在每次捕获后将CNT清零(可以用主从触发模式来自动完成CNT清零) 这样下次上升沿再捕获的时候 取出的CNT才是两个上升沿的时间间隔

2.输入捕获频率测量

本次实验用到测周法测频。在一个周期内标准频率为f_c,计一个数为1/f_c计数N次,则总共计数的时间为N/f_c.,则频率是给时间的倒数为f_c/N.f_c为内部时钟标准频率72MHz.因此我们只需要知道一个周期内计数的N为多少,这里的N指的是CNT计数自增锁存到通道1中的CCR1的值。所以

f_x=fc/CCR1

 测频法:在闸门时间T内,对上升沿计次,得到N ,则频率 f_x=N / T

测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率 f_x=f_c / N

中界频率:测频法与测周法误差相等的频率点 f_m=√f_c / T

3.主从触发模式

主从触发模式是主模式、从模式和触发源选择三个功能的简称

主模式:将定时器的内部信号映射到TRGO引脚上,用于触发别的外设。

从模式:用于接受其他外设或者自身外设的一些信号,用于控制自身定时器的运行。

触发源选择:指定的信号源选择TRGI去触发从模式。

本次实验中用T1FP1映射到TRGI去设置为Reset(目的:清楚CNT的值)

4.输入捕获基本结构

1.时基单元:用于产生f_c测量频率,在f_c频率的驱动下,CNT开始计数。

2.输入捕获单元:输入的PWM方波信号通过GPIO引脚进入,首先经过滤波器对外界输入的干扰信号进行滤除,紧接着进行边缘检测极性选择,如果选择上升沿触发则波形按照原来的样子输入;如果选择下降沿触发,则波形翻转,经过极性选择后,产生TI1FP1触发信号。经过分频器(这里的分频器选择不分频)。从模式选择复位操作 这样TI1FP1的上升沿也会通过上面这一路去触发CNT清零 当然这里会有个先后顺序 肯定是得先转运CNT的值到CCR里去 再触发从模式给CNT清零 

CNT的计数值是有上限的 由于ARR最大为65535 故CNT最大也只能计65535个数 如果信号频率太低 CNT的计数值可能会溢出 
从模式的触发源选择中有TI1FP1和TI2FP2 但是没有TI3和TI4的信号 所以如果要使用从模式自动清零CNT 就必须使用通道1或通道2作为输入 对于通道3和通道4 就只能开启捕获中断 在中断中手动清0了

                                    如上图所示频率: f_x=fc/CCR1

5.PWMI基本结构

 (1)PWMI模式使用两个通道同时捕获一个引脚 通过TIFP1通道1测量频率 f_x=fc/CCR1,通过TIFP2通道2.测占空比.TI1FP1配置上升沿触发 ,右上图来看CCR1是一个完整的捕获周期。TI1FP2配置下降沿触发,即在电平跳转到下降沿时CCR2计数停止,即CCR2就是高电平期间的计数值。占空比在这里的就是Duty=CCR2/CCR1.

6.输入捕获步骤

(1)RCC开启时钟,把GPIO和TIM时钟打开

    //1.开启时钟TIM3的时钟线是APB1
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    //2.开启GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

(2)GPIO初始化,把GPIO配置成输入模式

GPIO_InitTypeDef GPIO_Inistructure;
	GPIO_Inistructure.GPIO_Mode= GPIO_Mode_IPU;//PWM输入设置为上拉输入
	GPIO_Inistructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_Inistructure.GPIO_Speed=  GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Inistructure);//读取结构体的参数

(3)配置时基单元,让CNT计数器在内部时钟的驱动下自增。

    //3.配置时钟源,选择TIM3为内部时钟
	TIM_InternalClockConfig(TIM3);
	//4.时基单元初始化
	 TIM_TimeBaseInitTypeDef  TIM_timBaseInitStructure;
	 TIM_timBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;//一分频
	 TIM_timBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	 TIM_timBaseInitStructure.TIM_Period=65536-1;//ARR
	 TIM_timBaseInitStructure.TIM_Prescaler=72-1;//PSC  fc=72/72=1MHz计数频率
	 TIM_timBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器是高级定时器才有的
	 TIM_TimeBaseInit(TIM3,&TIM_timBaseInitStructure);

(4)配置输入捕获单元(包含滤波器,极性,直连通道还是交叉通道,以及分频器)

 //5.配置输入捕获单元
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//定时器3的通道1
	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器
	TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Rising;//边沿检测极性选择上升沿触发
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//通道选择直连通道
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//触发信号分频器选择不分频
    TIM_ICInit(TIM3,&TIM_ICInitStructure);

(5)选择从模式的触发源,触发源选择TI1FP1。触发源选择后,选择从模式的Reset操作(目的是将CNT清0)。

//6.触发源选择
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
//7.从模式设置选择我ReSet将CNT计数清零
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);

(6)‘调用TIM_CMD,开启定时器

//8.启动定时器
	TIM_Cmd(TIM3,ENABLE);

6.输入捕获测频率和占空比

6.1IC.c函数

//输入捕获单元
#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//1.开启时钟TIM3的时钟线是APB1
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  
	//2.开启GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_Inistructure;
	GPIO_Inistructure.GPIO_Mode= GPIO_Mode_IPU;//PWM输入设置为上拉输入
	GPIO_Inistructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_Inistructure.GPIO_Speed=  GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Inistructure);//读取结构体的参数
	
	//3.配置时钟源,选择TIM3为内部时钟
	TIM_InternalClockConfig(TIM3);
	
	//4.时基单元初始化
	 TIM_TimeBaseInitTypeDef  TIM_timBaseInitStructure;
	 TIM_timBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;//一分频
	 TIM_timBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	 TIM_timBaseInitStructure.TIM_Period=65536-1;//ARR
	 TIM_timBaseInitStructure.TIM_Prescaler=72-1;//PSC  fc=72/72=1MHz计数频率
	 TIM_timBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器是高级定时器才有的
	 TIM_TimeBaseInit(TIM3,&TIM_timBaseInitStructure);
    //5.配置输入捕获单元设置成两个通道捕获一个引脚
	//通道一直连 上升沿触发,测频率
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//定时器3的通道1
	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器
	TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Rising;//边沿检测极性选择上升沿触发
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_IndirectTI;//通道选择直连通道
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//触发信号分频器选择不分频
    TIM_ICInit(TIM3,&TIM_ICInitStructure);
	
	//通道2下降沿触发,测占空比
	TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);//这个函数的意义是将剩下的通道初始化为相反的配置
   //即将通道2设置为 交叉下降沿触发
//	TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//定时器3的通道2
//	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器
//	TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Falling ;//边沿检测极性选择下降沿触发
//	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//通道选择交叉通道
//	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//触发信号分频器选择不分频
//    TIM_ICInit(TIM3,&TIM_ICInitStructure);
	
	//6.触发源选择
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	//7.从模式设置选择我ReSet将CNT计数清零
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//8.启动定时器
	TIM_Cmd(TIM3,ENABLE);
}
//获取频率的函数
uint32_t  IC_GetFreq(void)
{
	return 1000000/(TIM_GetCapture1(TIM3)-1);//  fc/N=最新一个周期的频率值
}//TIM_GetCapture1(TIM3)通道1获得CCR1的值
//获取占空比的函数
uint32_t  IC_GetDuty(void)
{
	//(TIM_GetCapture2(TIM3)通道2获得CCR的值
	return (TIM_GetCapture2(TIM3)+1)*100/ (TIM_GetCapture1(TIM3)+1);//通道2获取的CCR2/通道1获取的CCR1
//有误差,因此进行加1操作
}

6.2main函数

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

uint8_t i;
int main(void)
{
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1,1,"Freq:00000Hz");
	OLED_ShowString(2,1,"Duty:  %");
	PWM_SetPrescaler(7200);     //f=72MHZ/PSC+1/ARR+1=1KHz
	PWM_SetCompare1(80);       //占空比  50/100=50%
    while(1)
	{	
		OLED_ShowNum(1,6,IC_GetFreq(),5);
		OLED_ShowNum(2,6,IC_GetDuty(),2);
	}
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值