STM32 PWM捕获 两种方法详解

前言:

        今天是2018蓝桥杯省赛的前一天,特此发表一篇以示纪念!

      STM32 的TIM的捕获PWM波,是为了频率和占空比,这两种数据结果!它 的最基本的原理就是(打个比方):例如一个高电平上升沿过来,捕获的数值就是上升为的高电平的TIM的计数值(TIM定时器,CNT不断增加,再重新装载),这点是最基本的内容!后面就是通过前后的数值计算可以获得占空比 频率。

第一种方法:
 官方的正统方法
   IC1和IC2为一组通道,IC3和IC4为一组通道,以上图为例可以得到上升沿是IC1的值为600(假设),此时TIMx_CCR2不变,计数器复位为0,然后在下降沿的时候,IC2读取计数值 即为高电平时间300(假设),当道下一个周期的上升沿时,IC1读取为600,计数器复位为0;

void pwmIC_Init()
{
	
		GPIO_InitTypeDef GPIO_InitStructure;
		NVIC_InitTypeDef NVIC_InitStructure;

		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOA, &GPIO_InitStructure);


		TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
		TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
		TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
		TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
		TIM_ICInitStructure.TIM_ICFilter = 0x0;

		TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

		TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);

		TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

		TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

		TIM_Cmd(TIM3, ENABLE);

		TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);

		NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);

}

这里最关键的就是TIM_ICPolarity_Rising 为上升沿开始捕获,TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);
选择IC2为有效的输入端,就是IC2获得的就是周期了,而IC1就是在这里就是高电平的时间! 假设周期:600,高电平时间:300
可以计算的得到占空比  = 300/600, 可以得到频率 =72M/ 600;
void TIM3_IRQHandler(void)
{

  TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

  IC2Value = TIM_GetCapture2(TIM3);

  if (IC2Value != 0)
  {

    DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;


    Frequency = SystemCoreClock / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}

以上就可以看出IC2为周期,IC1为高电平时间!

第二种方法:
     第二种方法显得比较裸,采用的就只是获取前后两次上升沿中断的计数值差,来计算周期,从而计算频率!
void TIM_Cap_Init(u16 arr,u16 prc)//²¶»ñƵÂʳõʼ»¯  
{  //PA1 PA2 ¶¨Ê±Æ÷TIM2 ͨµÀ2 3
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	NVIC_InitTypeDef  NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_TimeBaseInitStructure.TIM_Prescaler=71;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up ;
	TIM_TimeBaseInitStructure.TIM_Period=arr;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;  
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;   
	TIM_ICInitStructure.TIM_ICFilter=0x0;
	TIM_ICInit(TIM2,&TIM_ICInitStructure);
	
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_3;
	TIM_ICInit(TIM2,&TIM_ICInitStructure);
	
	TIM_Cmd(TIM2,ENABLE);
	TIM_ITConfig(TIM2, TIM_IT_CC2 | TIM_IT_CC3,ENABLE);
	
}

配置了IC2,和IC3来采集两路的周期值!

void TIM2_IRQHandler(void)
{
	
	if(TIM_GetITStatus(TIM2,TIM_IT_CC2)==SET)
	{
	  TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
		if(flag1==0)
	    {
	       one=TIM_GetCapture2(TIM2);
		   flag1=1;	
	    }
	   else if(flag1==1)
	   {
	     two=TIM_GetCapture2(TIM2);
	       if(two>one)
		   { 
			value1=(two-one);   
		   }
	      else
		  {  
			  value1=((0xffff-one)+two);
		  }
	   Get_pinlv1=36000000/value1/36;
		flag1=0;  
	
	   }
	}

  if(TIM_GetITStatus(TIM2,TIM_IT_CC3)==SET)
	{
	  TIM_ClearITPendingBit(TIM2,TIM_IT_CC3);
		if(flag2==0)
	    {
	       three=TIM_GetCapture3(TIM2);
		   flag2=1;	
	    }
	   else if(flag2==1)
	   {
	     four=TIM_GetCapture3(TIM2);
	       if(four>three)
		   { 
			value2=(four-three);   
		   }
	      else
		  {  
			  value2=((0xffff-three)+four);
		  }
	   Get_pinlv2=36000000/value2/36;
		flag2=0;  
	
	   }
	}
	
}

采用了点小操作,来计算前后两次上升沿的差!当然了,如果想要获取占空比的画,可以配置一个通道下降沿捕获,配合上升沿捕获即可,这里就不再示范了。

欢迎指点,互相学习!

扫描二维码关注公众号,回复: 1372962 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_37389133/article/details/79772878
今日推荐