STM32 TIM1输入捕获配置

       最近做一个IRIG-B码对时的项目用到STM32的TIM1输入捕获功能,配置TIM1的输入捕获遇到很多坑,在这里总结下,希望对大家有帮助。

          项目中用到的输入引脚为PE13,为TIM1_H3即TIM1的第3通道,这里提醒大家在使用引脚功能时最好查看引脚的重映象表,看是否要开启重映象,功能为捕获高电平脉宽,具体配置如下:

1.首先配置GPIO

/* GPIO引脚配置 */
void R_gpio_init(void)      
{	
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);//开启引脚时钟

	GPIO_PinRemapConfig(GPIO_FullRemap_TIM1,ENABLE);  //开启TIM1重映象

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;         //PE13     
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     //引脚设置为上拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStructure);
}

2.配置TIM1

/* TIM1输入捕获配置 */
void Time_init(void) 
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_ICInitTypeDef TIM1_ICInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //TIM1 时钟使能

	TIM_ClearITPendingBit(TIM1, TIM_IT_Update );     //清除TIM1更新中断标志 

	//定时器 TIM1 初始化
	TIM_TimeBaseStructure.TIM_Period = 7199; //设置自动重装载寄存器的周期值,使100ms产生一次中断
	TIM_TimeBaseStructure.TIM_Prescaler = 999; //设置预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分频系数
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //初始化 TIM1

	//TIM1输入捕获参数配置
	TIM1_ICInitStructure.TIM_Channel = TIM_Channel_3; //捕获通道IC3
	TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
	TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //直接映射
	TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //不分频,每个变化沿都捕获
	TIM1_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
	TIM_ICInit(TIM1, &TIM1_ICInitStructure);

	//中断优先级 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; //TIM1 捕获中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
	NVIC_Init(&NVIC_InitStructure); //初始化 NVIC 寄存器

	TIM_ITConfig(TIM1,TIM_IT_Update|TIM_IT_CC3,ENABLE);       //使能更新中断和捕获中断

	TIM_Cmd(TIM1, ENABLE);         //使能定时器
}

配置TIM1的时候有几点要很小心:

        1.TIM1在APB2时钟总线上,所以应使用RCC_APB2PeriphClockCmd()函数使能TIM1时钟;

        2.TIM1有多种中断,这里选择捕获比较中断,即TIM1_CC_IRQn;

        3.引脚为TIM1_CH3,即TIM1的3通道,中断标志位TIM_IT_CC3。

3.中断服务函数配置

/*    TIM1 中断服务程序   */
void TIM1_CC_IRQHandler(void)          
{	
  if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查TIM1更新中断标志 
  {
    overflow++;
  }
  else if (TIM_GetITStatus(TIM1, TIM_IT_CC3) != RESET) //检查TIM1通道3捕获中断标志
  {
    if(state == START)		//初始状态	
    {	
            overflow = 0;
            TIM_SetCounter(TIM1,0);
            state = WAIT_FALLING;
            TIM_OC3PolarityConfig(TIM1,TIM_ICPolarity_Falling);		//设置为下降沿捕获
    }	
    else if(state == WAIT_RISING)    //捕获上升沿
    {	
       //     TIM1CH3_CAPTURE_VAL = TIM_GetCapture3(TIM1);     
       //     value = TIM1CH3_CAPTURE_VAL + (overflow*7200);	
		
            overflow = 0;
            TIM_SetCounter(TIM1,0);
            state = WAIT_FALLING;
            TIM_OC3PolarityConfig(TIM1,TIM_ICPolarity_Falling); //设置为下降沿触发				
    }
    else // 捕获下降沿
    {
            TIM1CH3_CAPTURE_VAL = TIM_GetCapture3(TIM1);
            value = TIM1CH3_CAPTURE_VAL + (overflow*7200);

            overflow = 0;
            TIM_SetCounter(TIM1,0);
            state = WAIT_RISING;
            TIM_OC3PolarityConfig(TIM1,TIM_ICPolarity_Rising); //设置为上升沿触发		
    }		
  }
  TIM_ClearITPendingBit(TIM1, TIM_IT_Update|TIM_IT_CC3 );     //清除TIM1更新中断标志和捕获标志 
}

这里需要注意几点:

       1.TIM1的中断服务函数名要注意,此次用到的是TIM1的捕获比较中断,所以为void TIM1_CC_IRQHandler(void);

       2.改变捕获极性的函数要注意,此处为改变通道3捕获极性的函数,所以为TIM_OC3PolarityConfig();

       3.通道3获取捕获值函数为TIM_GetCapture3();

       4.因为我只需要高电平脉宽,所以只需要在捕获上升沿的时候获取捕获值即可。

经过测试高电平脉宽为10毫秒时捕获值为720,5ms时捕获值为360。

公式为:脉宽=((1 + TIM_Prescaler)/系统时钟频率)*捕获值

你可能感兴趣的:(STM32)