目录
一、概念
二、输入捕获的结构图
三、配置的基本步骤
一、概念
STM32的输入捕获功能是一种强大的特性,他允许处理器捕获外部输入信号,并基于定时器抓取输入信号指定触发方式(上升沿/下降沿)之间的长度。这对于测量信号的脉宽,频率和周期非常有用。
输入捕获通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变时,将当前定时器的值(TIMx_CNT)存放到对应的输入捕获寄存器(CCR)中,完成一次捕获。 可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数 每个高级定时器和通用定时器都拥有4个输入捕获通道 可配置为PWMI模式,同时测量频率和占空比 可配合主从触发模式,实现硬件全自动测量。
其中,输入捕获支持以下三种捕获方式:
- 上升沿触发:当信号从低电平跳变到高电平时触发。
- 下降沿触发:当信号从高电平跳变到低电平时触发。
- 上下都触发:同时捕获上升沿和下降沿,以便测量信号的完整周期。
对于测量频率,我们一般有两种方法:
1.直接测频率法:先开启定时器,记录信号来临的次数,一个周期/多个周期后,这个次数直接就是频率值。
2.测量周期间接测量频率法:先开启定时器,在信号来临时记录一次当前定时器的值T1,然后在第二次信号来临的时候记录定时器的值T2,则时间差为T2-T1,即周期,取到数则得到了频率。
这两种方法各有优点:直接法适合测量频率较高的信号;间接法适合测量频率较低的信号。这个较高和较低一般通过中界频率来衡量,如果大于中界频率则使用直接法,小于则使用间接法。
二、输入捕获的结构图
这里的主从触发模式选择:可以让GPIOA在有信号输入的时候,在TI1FP1时,兵分两路,一路往下让CCR寄存机锁存CNT计数器的值;另一路让TIM2计数器自动清零CNT计数器。这样我们从第二次开始,读取 到CCR寄存器中的值就直接是计数值了。
三、配置的基本步骤
1.开启时钟:
首先,需要使能TIM2(作为计数器)和相应GPIO引脚(作为信号输入口)的时钟。
2.配置引脚:
将GPIO引脚配置为复用功能,并设置为输入模式。
3.配置基本定时器:
初始化TIM2的基本参数,如预分频器、计数器模式和自动重装载值。
4.配置输入捕获:
设置输入捕获的通道映射、预分频、滤波和触发极性。
5.使能捕获通道和定时器:
最后,使能捕获通道和定时器开始工作。
6.配置中断和编写中断服务程序:(每过一段时间看一下CCR寄存器的值)
配置NVIC中断优先级,并编写中断服务程序来处理捕获事件。
//打开时钟
void Open_Timer()
{ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 假设使用GPIOA的某个引脚作为输入
}//配置GPIOA_0的引脚为输入模式
void Init_GPIOA()
{GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // X为具体的引脚号GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 或者设置为上拉/下拉输入,根据需要GPIO_Init(GPIOA, &GPIO_InitStruct);
}//配置TIM2定时器的计数功能
void Init_TIM2_Count()
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = 65536 - 1; // 设置自动重装载值---计数周期TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 设置预分频器,根据需要调整TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//不分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
}//配置输入捕获
void Init_TIM2_Capture()
{TIM_ICInitTypeDef TIM_ICInitStructure;TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; // 使用TIM2的通道1TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 输入信号的上升沿触发TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // //输入信号交叉,选择直通,不交叉TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 输入信号不分频,每一个信号都触发捕获TIM_ICInitStructure.TIM_ICFilter = 0x0F; // 输入信号滤波TIM_ICInit(TIM2, &TIM_ICInitStructure);
}//选择触发源及模式
void Init_Mode()
{TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //触发源选择TI1FP1TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //从模式选择复位 //即TI1产生上升沿时,会触发CNT归零
}void Init_NVIC()
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void Init_IC()
{Open_Timer();Init_GPIOA();Init_TIM2_Count();Init_TIM2_Capture();Init_Mode();Init_NVIC();
}//中断服务函数
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET){// 读取捕获值uint32_t capture_value = TIM_GetCapture1(TIM2);// 清除中断标志TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);// 在这里处理捕获值,例如计算信号的周期或频率}
}