STM32测量PWM波频率及占空比

PWM模式输入

该方式是在STM32输入捕获模式基础上扩展升级的功能,可以测量PWM波的频率及占空比,需要多加一个输入捕获寄存器

基本原理

(1)实现PWM输入捕获需要占用TIMx的两个通道,以IC1、IC2为例,TI1引脚上电平可被第1通道和第2通道同时监测到,两个通道分别被设置为主机和从机,如果设置第1通道为PWM输入捕获功能,则第2通道为从机。(IC1和IC2 IC3和IC4是成对存在的)
在这里插入图片描述

(2)输入的PWM从高电平跳变,第1个下降沿来临时,IC1 IC2均可监测到,从机设置为复位模式,将TIMx的计数器复位至0(此时不会产生计数器更新中断,因为无溢出)

(3)下一个上升沿来临时,IC2发生捕获事件,将当前计数器CNT的值存储至CCR2中,记为IC2_DATA2

(4)第二个下降沿来临,IC1发生捕获事件,将当前计数器CNT的值存储至CCR1中,记为IC1_DATA1在这里插入图片描述
5)PWM波信号频率

​ f=72*10^6 /(psc(预分频系数)+1)/ IC1_DATA1

​ 占空比D=IC2_DATA2/IC1_DATA1

频率f=72*10^6 /(psc(预分频系数)+1)/ IC1_DATA1

其中预分频系数这一项可以不加,如果不设置TIM_TimeBaseStructure.TIM_Prescaler这一项,则默认预分频系数为0,即此时:

​ 频率f=72*10^6 / IC1_DATA1

​ 此时可监测的频率范围为 72*10^6/65536(1098.6 Hz) ---- 72MHz,低于1098.6 Hz的频率将无法监测

​ 故设置预分频系数 psc,降低其可监测的范围(最大监测值和最小监测值都会改变)

实验(PWM输入部分代码)

基于STM32F103MiNi开发板(正点原子),以定时器3为例,TIM3_CH1(PA6引脚),由定时器4(TIM4_CH3 PB8引脚)产生PWM波,通过杜邦线外接PB8和PA6引脚

/*定时器3  PWM波输入捕获部分*/
void TIM3_Init(u16 psc)   //形参为分频系数
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_ICInitTypeDef  TIM_ICInitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

 	RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB1Periph_TIM3, ENABLE);  //时钟初始化

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  
	GPIO_Init(GPIOA, &GPIO_InitStructure);      //引脚初始化
	 
	TIM_TimeBaseStructure.TIM_Period = 65535; 	//计数器自动重装值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 	//预分频系数
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;   //重复溢出次数,设置为0
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); 
  
	//通道1
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //IC1
   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;	//下降沿捕获
   TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //IC1映射到TI1上
   TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //配置分频模式,不分频
   TIM_ICInitStructure.TIM_ICFilter = 0x00;                //配置输入滤波模式,不滤波
   TIM_ICInit(TIM3, &TIM_ICInitStructure);

	//中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);  

	TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);  

	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);  //选择TIM3输入触发源  TI1

	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);  /选择从机模式,复位模式

	TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);  //开启复位模式

	TIM_Cmd(TIM3,ENABLE ); 	//使能计数器

	TIM_ITConfig(TIM3,TIM_IT_CC1,ENABLE);//使能中断
}

//中断部分
void TIM3_IRQHandler(void)
{
    
    
  static float  Duty;
  static float IC1_DATA1;   //IC1_DATA1  、IC2_DATA2 定义为float类型,否则Duty会显示0
  static float IC2_DATA2;   //
  static u16 Frequence;
  TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);

 IC1_DATA1 = TIM_GetCapture1(TIM3);
  IC2_DATA2 = TIM_GetCapture2(TIM3);
  if (IC1_DATA1 != 0)
  {
    
    
    Frequence = (72000000/IC1_DATA1/(psc+1)); //psc为TIM3_Init(u16 psc)初始化的形参,值相同
  }
  else
  {
    
    
    Frequence = 0;
  }
  Duty=IC2_DATA2/IC1_DATA1;   //获得占空比
  printf("占空比=%%%.1f \r\n",(Duty*100));
  printf("PWM波频率=%d Hz \r\n",Frequence);
}


定时器4产生PWM波部分,直接借鉴正点原子官方 PWM波输出实验即可。

工程:PWM模式输入

测量一段时间内脉冲个数求频率

用TIM3_IRQHandler()中断计数PWM波脉冲个数,此时需要用另外一个定时器TIMx作为时钟计时,此时用定时器7作为计时时钟,定时器4产生PWM波

//TIM3 初始化
void TIM3_Init(u16 arr,u16 psc)   //形参为分频系数
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_ICInitTypeDef  TIM_ICInitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

 	RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB1Periph_TIM3, ENABLE);  //时钟初始化

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  
	GPIO_Init(GPIOA, &GPIO_InitStructure);      //引脚初始化
	 
	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_TimeBaseStructure.TIM_RepetitionCounter=0;   //重复溢出次数,设置为0
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); 
  
	//通道1
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //IC1
   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;	//下降沿捕获
   TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //IC1映射到TI1上
   TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //配置分频模式,不分频
   TIM_ICInitStructure.TIM_ICFilter = 0x00;                //配置输入滤波模式,不滤波
   TIM_ICInit(TIM3, &TIM_ICInitStructure);

	//中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);  

    TIM_CtrlPWMOutputs(TIM8,ENABLE);
   
	TIM_Cmd(TIM3,ENABLE ); 	//使能计数器

	TIM_ITConfig(TIM3,TIM_IT_CC1,ENABLE);//使能中断
}

//中断部分
void TIM3_IRQHandler(void)
{
    
    
  static u16 Frequence=0;
  static float time;
  static unsigned int PWMone=0;
  TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);

  Frequence++;  //脉冲个数加1
  if((PWMTimer - PWMOneMinute)>99)  //定时1s更新一次,此处由另一定时器7提供时间基准
	{
    
    
			PWMOneMinute=PWMTimer;  	       //重新开始计时
			time=Frequence/10;				//计算得到频率(1s内脉冲个数)	
			Frequence=0;	  					//重新开始计数
  
			printf("PWM波频率=%d Hz",Frequence);
  	}
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44333597/article/details/107597740