
需要明确需要什么资源、是否复用、是否重映射
定时器的输入捕获模式
同样的只有基本定时器没有这个功能,通用定时器和高级定时器是有这个功能的
定时器的输入捕获模式,也就是检测外部的一个波形,检测的触发方式,是边沿检测,和外部中断一样的,但是看似差不多的功能,实际上差别还是挺大的
外部中断进行的边沿检测是没有滤波功能的,而采用定时器的输入捕获是有滤波功能,并且还可以对输入的波,进行分频,对(定时器产生的)采样信号也可以进行分频
而且在中断中,捕获也是对应了一个中断(TIM_IT_CC),溢出(更新)也同样也对应一个中断(TIM_IT_UpDate);外部中断对应的标志位则是对应的中断线(例如:EXTI_Line11)
作用
可以对外部信号进行较为精确的采集输出,可以用来作为采集心率、脉搏等等,某一动作的出发时间等等 ;例如检测按键按下了3s开始复位
实现流程
明确需要的资源(定时器、输入的引脚、是否复用、是否映射)
开启对应的时钟
引脚初始化
定时器初始化
定时器输入捕获模式初始化
定时器中断初始化
定时器的中断服务程序,要注意输入捕获的标志位是TIM_IT_CCX ( X代表通道几 )
代码
#include "catch_channel.h" //这是一个用来测试定时器输入捕获的 //目的:检测到按键按下的时间,并且再传口中打印出具体的时间 //已知:按键K1是 PA11 //需要用到的资源是:定时器1的通道4,这个是PA11的复用功能、定时器1的中断 u16 Catch_Time = 0; //这个是记录捕获时间的,每进一次中断就++,一次中断时0.1ms u16 Catch_Flag = 0; u16 Old_Catch_Time = 0; //旧的捕获时间 u16 New_Catch_Time = 0; //新的捕获时间 ///引脚初始化 void Catch_GPIO_Init(){ GPIO_InitTypeDef GPIO_InitStructrue; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE ); GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOA, &GPIO_InitStructrue ); GPIO_SetBits( GPIOA, GPIO_Pin_11 ); } ///定时器1初始化 void Catch_TIM1_Init(){ TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE ); TIM1_TimeBaseInitStructure.TIM_Period = 3599; //APB1上的时钟最大是36M,此时一个脉冲也就是3600/36000000=0.0001s=0.1ms TIM1_TimeBaseInitStructure.TIM_Prescaler = 0; TIM1_TimeBaseInitStructure.TIM_ClockDivision =0; TIM1_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up; TIM_TimeBaseInit( TIM1, &TIM1_TimeBaseInitStructure ); } ///定时器1模式初始化 void Catch_TIM1_Mod_Init(){ TIM_ICInitTypeDef TIM1_ICInitStructure; TIM1_ICInitStructure.TIM_Channel = TIM_Channel_4; TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //设置输入捕获方式 下降沿捕获 TIM1_ICInitStructure.TIM_ICPrescaler = 0; //设置输入捕获的分频系数 TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //将捕获通道映射在定时器的通道上 TIM1_ICInitStructure.TIM_ICFilter = 0x00; //配置滤波器,此时不配置滤波器 TIM_ICInit( TIM1, &TIM1_ICInitStructure ); } ///定时器1的中断 void TIM1_NVIC_Init(){ NVIC_InitTypeDef TIM1_NVIC_InitStructure; //NVIC_PriorityGroupConfig( NVIC_PriorityGroup_0 ); TIM1_NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; TIM1_NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; TIM1_NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; TIM1_NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&TIM1_NVIC_InitStructure); TIM_ITConfig( TIM1,TIM_IT_Update|TIM_IT_CC4, ENABLE ); //开启对应的中断 TIM_Cmd( TIM1, ENABLE ); } ///硬件初始化 void Catch_Channel_Hard_Init(){ Catch_GPIO_Init(); Catch_TIM1_Init(); Catch_TIM1_Mod_Init(); TIM1_NVIC_Init(); } ///定时器1的更新中断 ,在此中断中,实现了查看按键按下的时间 void TIM1_UP_IRQHandler(){ if(TIM_GetFlagStatus( TIM1, TIM_IT_CC4 ) == SET ){ //被置位了 ,第一次的时候,说明捕获到了(边沿)下降沿,也就是说按键按下了 Catch_Flag = ~Catch_Flag; if( Catch_Flag == 0){ if( Catch_Time < 0xFFFF ){ //小于变量(16位)的最大值 New_Catch_Time = Catch_Time; //记录下松开按键的时间 }else{ printf("太大了\r\n"); } //将通道4的输入捕获方式重新设置为下降沿捕获,以便下一次的使用 TIM_OC4PolarityConfig( TIM1, TIM_ICPolarity_Falling );// //清除标志 TIM_ClearFlag( TIM1,TIM_IT_Update|TIM_IT_CC4 ); //计算一下时间,打印出来 printf("时间:%d ms\r\n",(int)((New_Catch_Time - Old_Catch_Time)*0.1) ); //进入一次中断就是0.1ms }else{ printf("%d\r\n",Catch_Flag); //记录下按键按下的时间 Catch_Time = 0; Old_Catch_Time = Catch_Time; //设置上升沿触发,等待松开按键 TIM_OC4PolarityConfig( TIM1, TIM_ICPolarity_Rising); //将通道4的输入捕获设置为上升沿捕获 //清除标志 TIM_ClearITPendingBit( TIM1,TIM_IT_Update|TIM_IT_CC4); } printf("kkk"); TIM_ClearITPendingBit( TIM1,TIM_IT_CC4); } Catch_Time++; TIM_ClearITPendingBit( TIM1, TIM_IT_Update); }
#好好学习!