stm32输入捕获

Posted 旭日初扬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32输入捕获相关的知识,希望对你有一定的参考价值。

一、输入捕获简介

 

  • STM32F1 除了基本定时器 TIM6 和 TIM7,其他定时器都具有输入捕 获功能。
  • 输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,通 常用于测量输入信号的脉宽、测量 PWM 输入信号的频率及占空比。
  • 在输入捕获模式下,当相应的 ICx 信号检 测到跳变沿后,将使用捕获/比较寄存器(TIMx_CCRx)来锁存计数器的值。

TIMx_CHx (定时器的独立通道)

通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/ 下降沿)的时候,将当前 定时器的值(TIMx_CNT) 存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中 断/DMA 等

二、原理

 图片来源:普中科技stm32f1xx开发攻略

假定t1~t2是需要测量的高电平时间 ,定时器工作在向上计数模式。

测量方法:

  1. 先设置定时器通道 x 为上升沿捕获,t1 时刻捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x 为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记 为 CCRx2。根据定时器的计数频率,算出 t1-t2 的时间,从而得到 高电平脉宽。
  2. 在 t1-t2 时间内可能会出现 N 次定时器溢出,因此需要对定 时器溢出进行处理,防止因高电平时间过长发生溢出导致测量数据不准。CNT 计 数的次数等于:N*ARR+CCRx2
  3. 高电平的持续时间(t1到t2的时间)CNT计数次数  *  CNT的计数周期。
  4. 16 位自动重载计数器(CNT)。

三、代码

概念补充:

  • 输入捕获通道就: IC1/2/3/4
  • 通用定时器的输入通道有 4 个 TIMx_CH1/2/3/4。通常 也把这个 4 个通道称为 TI1/2/3/4

3.1、TIM5初始化

#include "public.h"
/*
Fuction:
 

*/
// TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
// TIM 捕捉比较1  中断源

/*
Annotation to practice

FuctionName:TIM5_CH1_Input_Init
Author/Writer: YI
Date:     2021/10/11
Fuction:  TIM5_CH1 input  Capture
InputName/Inpt Parameter:
Returned Value: NULL
Update/ amendant record:

*/
void TIM5_CH1_Input_Init(u16 arr,u16 psc)
{
	//  stm32f10x_tim.h   定时器初始化定义
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	//  stm32f10x_tim.h   定时器输入捕捉结构体定义
	TIM_ICInitTypeDef        TIM_ICInitStructure;
	
	// MISC.h             中断嵌套结构体初始化定义
	NVIC_InitTypeDef         NVIC_InitStructure;
	
	// stm32f10x_gpio.h   GPIO初始化结构定义
	GPIO_InitTypeDef         GPIO_InitStructure;
	
	//  输入捕获是通用定时器的一个功能,因此需要使能相应定时器时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
	
	// 使用 TIM5 的 CH1 通道来测量输入信号的脉宽
	// TIM5 的 CH1 通道对应的管脚是 PA0, 因此要使能 GPIOA 端口时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//  们使用 PA0 来测量输入信号的高电平 时间,因此需要将 PA0 配置为下拉输入模式。
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;       // 管脚设置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 下拉输入
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	// 设置定时器自动重载计数周期值,在事件产生时更新到影子寄 存器。可设置范围为 0 至 65535。
	TIM_TimeBaseInitStructure.TIM_Period = arr;     // 自动装置值  定时器周期
	
	//  定时器的预分频器系数,时钟源经过该预分频器后输出的 才是定时器时钟
	//  设置值范围:0-65535,分频系数由于是除数,分母不能为 0, 所以会自动加 1,最后实现 1-65536 分频
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;  // 分频系数
	
	// 时钟分频因子,设置定时器时钟 CK_INT 频率与数字 滤波器采样时钟频率分频比。
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频
	
	//  比较常用的是向上计数模式(TIM_CounterMode_Up)和向下 计数模式(TIM_CounterMode_Down)。
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //  定时器的计数方式
	
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);	
	
	//  输入捕获通道设置,通用定时器每个多达 4 个通道,假如使用 TIM5 的通道 1,参数为 TIM_Channel_1。
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;  // 通道1
	
	// 滤波长度设置,不使用滤波器,参数为 0。 
	// 如果我们需要配置 TIM5 的通道 1 为输入捕获功能,并且为上升沿捕获、不 分频、直接映射到 TI
	TIM_ICInitStructure.TIM_ICFilter = 0x00;          //  滤波
	
	// 输入信号的有效捕获极性设置,对输入信号 上升沿开始捕获,参数为 TIM_ICPolarity_Rising,
	// 如果是下降沿捕获,参数为 TIM_ICPolarity_Rising
	// 单独设置通道捕获极性的函数,假 如要修改 TIM5 的通道 1 捕获极性为下降沿
	//  TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);
	// 此函数可以理解为通用函数 TIM_OCxPolarityConfig(),函数中的 x 表示通 道,
	// 如果是对通道 2 捕获极性操作,可以调用 TIM_OC2PolarityConfig 函数。
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 捕获极性
	
	//  分频系数设置,分频系数可以为 TIM_ICPSC_DIV1、 TIM_ICPSC_DIV2、TIM_ICPSC_DIV4、TIM_ICPSC_DIV8,
	//  不分频,参数为 TIM_ICPSC_DIV1。
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;       // 分频系数
	
	//  映射设置  ICx 可以映射到 2 个 TIx 上(参考定时器结构 框图)
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 直接映射到TI1
	TIM_ICInit(TIM5,&TIM_ICInitStructure);
	
	/*
	定时器溢出中断
	检测输入信号的高电平脉宽
	上升沿来时捕获一次,然后设置为下降沿,等下降沿来时有捕获一次,即高电平脉宽
	如果高电平脉宽较长,那么定时器可能溢出,溢出则计算的高电平时间不准  所以要开启定时器溢出中断
	
	*/
	TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;           // 中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占式优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        // 副优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM5,ENABLE);
}

以上是关于stm32输入捕获的主要内容,如果未能解决你的问题,请参考以下文章

如何让stm32产生多路输出 PWM 最好有代码

STM32使用定时器实现输入捕获

stm32输入捕获

stm32输入捕获

STM32的输入捕获实验

绵绵STM32学习——输入捕获