STM32 TIM定时器的使用(2)——输入捕获

输入捕获实验是电容按键检测实验的前提所以需要先学习用TIM实现输入捕获

1、系列目录

  1. 基本计时实验
  2. 输入捕获实验(实验3的基础)
  3. 电容按键检测实验
  4. 输出PWM实验
  5. PWM驱动无刷电机实验

2 、输入捕获原理

定时器都有四个通道,我们需要将使用其中一个通道与开发板的按键相同,例如正点原子F1精英板的KEY_UP按键和TIM5_CH1为共用IO(PA0),所以我们只需要开启TIM5的捕获功能即可计时按键的高低电平变化。
所以要使用到
TIM_TimeBaseInitTypeDef和TIM_ICInitTypeDef这两个结构体,Base结构体已经在上一节解释,现在来分析IC这个结构体

3、IC结构体分析

TIM_ICInitTypeDef看名字就知道和输入有关,因为IC的I = in 输入
TIM_OCInitTypeDef当然也有OC O=out 输出,将会在PWM实验中使用到

typedef struct
{
    
    

  uint16_t TIM_Channel;      /*!< Specifies the TIM channel.
                                  This parameter can be a value of @ref TIM_Channel */

  uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.
                                  This parameter can be a value of @ref TIM_Input_Capture_Polarity */

  uint16_t TIM_ICSelection;  /*!< Specifies the input.
                                  This parameter can be a value of @ref TIM_Input_Capture_Selection */

  uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
                                  This parameter can be a value of @ref TIM_Input_Capture_Prescaler */

  uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                  This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;

TIM_Channel:选择使用通道几进行捕获
TIM_ICPolarity:选择高电平、低电平、高低电平触发输入捕获
TIM_ICSelection:配置CCMR1寄存器的CC1S位
(00输出,01输入IC1映射在TI1上,10输入IC1映射在TI2上,11输入IC1映射在TRC上)
TIM_ICPrescaler:输入信号分频值
TIM_ICFilter:滤波器,多少次捕获触发一次中断

4 、捕获时间计算

捕获时间t :
t = num * T
总计数次数num:
num = (TIM5CH1_CAPTURE_STA & 0x3F)* arr + TIM5CH1_CAPTURE_VAL
时钟周期T:
基本计时实验中的第四部分已经分析过。

5、重点代码分析

在这里插入图片描述

如果分析不明白可以查看我对自定义寄存器这种办法的详细讲解 用户自定义寄存器详解

6、代码示例

/*
*TIM5配置
*/
void TIM5_Config(u16 arr,u16 psc)
{
    
    
	GPIO_InitTypeDef 			 GPIO_InitStructure;	
	
	TIM_TimeBaseInitTypeDef		 TIM_TimeBaseStructure;
	TIM_ICInitTypeDef			 TIM_ICInitStructure;	
	
	NVIC_InitTypeDef			 NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//PA0 配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//下拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);//提前强制拉低
	
	//TIM5基础配置	
	//计时器时钟 = APB总线时钟/分频因子
	//							psc
	TIM_TimeBaseStructure.TIM_Period = arr;//重装载值/最大计数值
	TIM_TimeBaseStructure.TIM_Prescaler = psc;//预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
	
	//TIM5输入捕获配置
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//选择TIM5的CH1通道
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//将IC1映射到IT1
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//信号分频值,不分频
	TIM_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
	TIM_ICInit(TIM5,&TIM_ICInitStructure);
	
	//中断优先级配置  优先级:2 0
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_ITConfig(TIM5,TIM_IT_Update | TIM_IT_CC1 ,ENABLE);// TIM5计数更新中断、CCR1捕获中断使能
	TIM_Cmd(TIM5,ENABLE);  //使能TIM5		
}
/*
*TIM5输入捕获 中断服务函数
*/
u8  TIM5CH1_CAPTURE_STA=0;	//输入捕获状态		    				
u16	TIM5CH1_CAPTURE_VAL;	//输入捕获值
int a=0;
void TIM5_IRQHandler(void)
{
    
    
	if((TIM5CH1_CAPTURE_STA & 0x80) == 0)//未捕获成功
	{
    
    
		if(TIM_GetITStatus(TIM5,TIM_IT_Update) != RESET) //再次检测是否有中断
		{
    
    	
			if(TIM5CH1_CAPTURE_STA & 0x40)//已经捕获到高电平
			{
    
    
				if((TIM5CH1_CAPTURE_STA & 0x3F) == 0x3F )//到达计时最大值,不能再进行计数;所有数据附上最大值
				{
    
    	
					TIM5CH1_CAPTURE_STA |= 0x80;//将捕获状态位(bit8)设为1,标记成功捕获
					TIM5CH1_CAPTURE_VAL = 0xFFFF;
				}
				else 
				{
    
    
					TIM5CH1_CAPTURE_STA++;
				}
			}
			
		}
		if(TIM_GetITStatus(TIM5,TIM_IT_CC1) != RESET)
		{
    
    
			if(TIM5CH1_CAPTURE_STA & 0x40)//从第一个高电平开始,捕获到第一个下降沿
			{
    
    
				TIM5CH1_CAPTURE_STA |= 0x80;//置位bit8,标记为一次捕获结束
				TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);
				TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);	//????????????????????????
			}				
			else//第一个高电平刚到
			{
    
    	
				TIM5CH1_CAPTURE_STA = 0;
				TIM5CH1_CAPTURE_VAL = 0;
				TIM_SetCounter(TIM5,0);	//全部清空
				TIM5CH1_CAPTURE_STA |= 0x40;//标记捕获到上升沿
				TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);//????????????????????????				
			}
		}

	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update | TIM_IT_CC1);//同时清空两个中断标志

}
/*
*main.c
*/
主函数中需要配置arr和psc,再根据TIM5CH1_CAPTURE_STA和TIM5CH1_CAPTURE_VAL的值计算出定时时间即可

猜你喜欢

转载自blog.csdn.net/qq_44011116/article/details/112982200