STM32 输入捕获工作过程(通道1为例)

通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。

输入捕获1滤波器 ICIF[3:0],这个用来设置输入采样频率和数字滤波器长度。其中,fck_INT
是定时器的输入频率(TIMxCLK),一般为 84Mhz,而fDTS则是根据 TIMx_CRI 的 CKD[1:0]
的设置来确定的,如果 CKD[1:0]设置为 00,那么fDTS=fcx_INT。N 值就是滤波长度,举个简
单的例子;假设 IC1F[3:0]=0011,并设置IC1映射到通道1上,且常g升沿触发。那么在捕获
到上升沿的时候,再以fck_INT的频率,连续采样到8次通道1 的电平,如果都是高电平,则说
明却是一个有效的触发,就会触发输入捕获中断(如果开启了的话)。这样可以滤除那些高电平
脉宽低于 8 个采样周期的脉冲信号,从而达到滤波的效果。这里,我们不做滤泼处理,所以设
置ICIF(3:0]=0000,只要采集到上升沿,就触发捕获。

通过设置CC1P的值来设置输入捕获的极性(上升沿/下降沿)。

通过设置CC1S[1:0]的值来设置输入捕获映射通道可以来自通道2。



输入捕获通道初始化函数:
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
typedef struct
{
uint16_t TIM_Channel; //捕获通道1-4
uint16_t TIM_ICPolarity; //捕获极性
uint16_t TIM_ICSelection; //映射关系
uint16_t TIM_ICPrescaler; //分频系数
uint16_t TIM_ICFilter; //滤波器
} TIM_ICInitTypeDef;
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM5_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
通道极性设置独立函数:
void TIM_OCxPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
获取通道捕获值
uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx);
输入捕获的一般配置步骤:
① 初始化定时器和通道对应IO的时钟。
② 初始化IO口,模式为复用:GPIO_Init();
③设置引脚复用映射: GPIO_PinAFConfig();
④初始化定时器ARR,PSC
TIM_TimeBaseInit();
⑤初始化输入捕获通道
TIM_ICInit();
⑥如果要开启捕获中断,
TIM_ITConfig();
NVIC_Init();
⑦使能定时器:TIM_Cmd();
⑧编写中断服务函数:TIMx_IRQHandler();
程序
实验目的:测量信号的脉冲宽度
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态
u32 TIM5CH1_CAPTURE_VAL;//输入捕获值(TIM2/TIM5 是 32 位)
void TIM_Init(u32 arr,u32 psc)
{
GPIO_InitTypeDef GPIO_Initer;
TIM_TimeBaseInitTypeDef TIM_TimeBaseIniter;
TIM_ICInitTypeDef TIM_ICIniter;
NVIC_InitTypeDef NVIC_Initer;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
GPIO_Initer.GPIO_Mode=GPIO_Mode_AF;
GPIO_Initer.GPIO_OType=GPIO_OType_PP;
GPIO_Initer.GPIO_Pin=GPIO_Pin_0;
GPIO_Initer.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_Initer.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_Initer);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);
TIM_TimeBaseIniter.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseIniter.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseIniter.TIM_Period=arr;
TIM_TimeBaseIniter.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseIniter);
TIM_ICIniter.TIM_Channel = TIM_Channel_1;
TIM_ICIniter.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICIniter.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICIniter.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICIniter.TIM_ICFilter = 0x00;
TIM_ICInit(TIM5,&TIM_ICIniter);
TIM_ITConfig(TIM5,TIM_IT_CC1|TIM_IT_Update,ENABLE);
NVIC_Initer.NVIC_IRQChannel=TIM5_IRQn;
NVIC_Initer.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initer.NVIC_IRQChannelPreemptionPriority=2;
NVIC_Initer.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_Initer);
TIM_Cmd(TIM5,ENABLE);
}
void TIM5_IRQHandler()
else TIM5CH1_CAPTURE_STA++;
}
}
if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获 1 发生捕获事件
else //还未开始,第一次捕获上升沿
{
TIM5CH1_CAPTURE_STA=0;//清空
TIM5CH1_CAPTURE_VAL=0;
TIM5CH1_CAPTURE_STA|=0X40;//标记捕获到了上升沿
TIM_Cmd(TIM5,ENABLE ); //使能定时器 5
TIM_SetCounter(TIM5,0); //计数器清空
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);//设置下降沿捕获
TIM_Cmd(TIM5,ENABLE ); //使能定时器 5
}
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}
int main(void)
}
}
在中断服务函数TIM5_IRQHandler用到了两个全局变量,用于辅助实现 高电平捕获。其中 TIM5CH1_CAPTURE_STA,是用来记录捕获状态,该变量类似我们在 usart.c 里面自行定义的 USART_RX_STA 寄存器(其实就是个变量,只是我们把它当成一个寄存器那样 来使用)。

另外一个变量 TIM5CH1_CAPTURE_VAL,则用来记录捕获到下降沿的时候,TIM5_CNT 的值。捕获高电平脉宽的思路:首先,设置 TIM5_CH1 捕获上升沿,这在 TIM5_Cap_Init 函数执行的时候就设置好了,然后等待上升沿中断到来,当捕获到上升沿中断, 此时如果 TIM5CH1_CAPTURE_STA 的第 6 位为 0,则表示还没有捕获到新的上升沿,就先把 TIM5CH1_CAPTURE_STA、TIM5CH1_CAPTURE_VAL 和计数器值 TIM5->CNT 等清零,然后 再设置 TIM5CH1_CAPTURE_STA 的第 6 位为 1,标记捕获到高电平,最后设置为下降沿捕获, 等待下降沿到来。如果等待下降沿到来期间,定时器发生了溢出(对 32 位定时器来说,很难溢 出),就在 TIM5CH1_CAPTURE_STA 里面对溢出次数进行计数,当最大溢出次数来到的时候, 就强制标记捕获完成(虽然此时还没有捕获到下降沿)。当下降沿到来的时候,先设置 TIM5CH1_CAPTURE_STA 的第 7 位为 1,标记成功捕获一次高电平,然后读取此时的定时器 值到 TIM5CH1_CAPTURE_VAL 里面,最后设置为上升沿捕获,回到初始状态。 这样,就完成一次高电平捕获了,只要 TIM5CH1_CAPTURE_STA 的第 7 位一直为 1, 那么就不会进行第二次捕获,在main函数处理完捕获数据后,将TIM5CH1_CAPTURE_STA 置零,就可以开启第二次捕获。
运行视频
输入捕获实验










