STM32 学习之旅 输入捕获

捕获输入,按字面意思便是捕获输入的信号,它可以用来测量脉冲宽度或者测量频率,通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。通俗点形容,最简单的:某个GPIO口一直是低电平,突然来了一个高电平,你想要知道高电平的时间到底有多长,这就是输入捕获。STM32里面,除开基本定时器TIM6和TIM7外,其他的定时器都有输入捕获功能,接下来开始捕获实验。
实验思路:初始化计数器,定时器向上或向下开始计数,设置某通道为上升沿捕获,等待高电平的到来,高电平一来,把计数器的值记录下来,再设置为下降沿捕获,等低电平一来,记录此时的计数器的值,这样,两次的差值就是脉宽了,同时定时器的计数频率我们是知道的,所以时间也可以求。
附上通道一捕获输入的工作图:STM32 学习之旅 输入捕获其中的相关的寄存器有圈出来,从左往右的配置为:
TIMx_CCMR1的ICF【3:0】:输入捕获 1 滤波器,用来设置输入采样频率和数字滤波器长度。
TIMx_CCER的CC1P:设置极性,0为上升沿捕获,1为下降沿捕获
TIMx_CCMR1的CC1S【1:0】:这两个位用于 CCR1 的通道方向配置, 这里我们设置 IC1S[1:0]=01,即是配置为输入,且 IC1 映射在 TI1 上, CC1 即对应 TIMx_CH1。
TIMx_CCMR1的ICPS【1:0】:输入捕获 1 预分频器。这里是 1 次边沿就触发 1 次捕获,所以选择 00 就是了。
TIMx_CCER的CC1E位:通道使能,0关闭输出通道,1开启输出通道
附上代码:
#include “Time.h”

void Time_Init()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//设置PA0为下拉输入
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin=GPIO_Pin_0;
gpio.GPIO_Mode=GPIO_Mode_IPD;
gpio.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gpio);

TIM_TimeBaseInitTypeDef time;
time.TIM_Period=7199;
time.TIM_Prescaler=9999;
time.TIM_CounterMode=TIM_CounterMode_Up;
time.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2,&time);

TIM_ICInitTypeDef timeic;
timeic.TIM_Channel=TIM_Channel_1;
timeic.TIM_ICPolarity=TIM_ICPolarity_Rising;;//设置为上升沿捕获
timeic.TIM_ICSelection=TIM_ICSelection_DirectTI;
timeic.TIM_ICPrescaler=TIM_ICPSC_DIV1;
timeic.TIM_ICFilter=0X00;
TIM_ICInit(TIM2,&timeic);

NVIC_InitTypeDef nvic;
nvic.NVIC_IRQChannel=TIM2_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority=2;
nvic.NVIC_IRQChannelSubPriority=2;
nvic.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&nvic);

TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM2,ENABLE);
}

void TIM2_IRQHandler()
{
int status=0;//判断是否采集到上升沿信号
if( (status&0x10) ==1)
{
if( (TIM_GetITStatus(TIM2,TIM_IT_CC1)) ==SET )//有信号来,触发捕获中断
{
Led_YellowTurn();
usart1_sendstr(“HELLO\r\n”);
status|=0x00;
TIM_OC1NPolarityConfig(TIM2,TIM_ICPolarity_Rising);//设置为上升沿捕获
TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);//清除中断标志
}
}
if( (TIM_GetITStatus(TIM2,TIM_IT_CC1)) ==SET )//信号来,触发捕获中断
{
Led_RedTurn();
status|=0x10;
TIM_OC1NPolarityConfig(TIM2,TIM_ICPolarity_Falling);//设置为下降沿捕获
TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);//清除中断标志
}

}
我做的实验并没有去计算高电平的时间,只是简单的用LED0和LED1灯各自闪烁一下,表示已经完成了高电平的捕获。