STM32 measures PWM wave frequency and duty cycle

PWM mode input

This method is an expanded and upgraded function based on the STM32 input capture mode. It can measure the frequency and duty cycle of the PWM wave, and an additional input capture register is needed.

Fundamental

(1) The realization of PWM input capture needs to occupy two channels of TIMx. Taking IC1 and IC2 as examples, the level on the TI1 pin can be monitored by the first channel and the second channel at the same time. The two channels are set as the host and Slave, if the first channel is set as the PWM input capture function, then the second channel is the slave. (IC1 and IC2 IC3 and IC4 exist in pairs)
Insert picture description here

(2) The input PWM jumps from a high level. When the first falling edge comes, IC1 and IC2 can be monitored. The slave is set to reset mode, and the TIMx counter is reset to 0 (the counter update will not be generated at this time Interrupted because there is no overflow)

(3) When the next rising edge comes, a capture event occurs in IC2, and the current counter CNT value is stored in CCR2, which is marked as IC2_DATA2

(4) The second falling edge is coming, IC1 has a capture event, and the current counter CNT value is stored in CCR1, which is recorded as IC1_DATA1 Insert picture description here
5) PWM wave signal frequency

​ f=72*10^6 /(psc(prescaler coefficient)+1)/ IC1_DATA1

​ Duty cycle D=IC2_DATA2/IC1_DATA1

Frequency f=72*10^6/(psc(prescaler coefficient)+1)/ IC1_DATA1

The prescaler coefficient can be omitted. If TIM_TimeBaseStructure.TIM_Prescaler is not set, the default prescaler coefficient is 0 , that is, at this time:

​ Frequency f=72*10^6 / IC1_DATA1

​ At this time , the frequency range that can be monitored is 72*10^6/65536 (1098.6 Hz) ---- 72MHz, and frequencies below 1098.6 Hz will not be able to be monitored

​ So set the prescaler coefficient psc to reduce its monitorable range (the maximum monitoring value and the minimum monitoring value will change)

Experiment (PWM input part of the code)

Based on STM32F103MiNi development board (punctual atom), take timer 3 as an example, TIM3_CH1 (PA6 pin), PWM wave is generated by timer 4 (TIM4_CH3 PB8 pin), and PB8 and PA6 pins are connected via DuPont line

/*定时器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);
}


Timer 4 generates the PWM wave part, and you can directly learn from the official PWM wave output experiment of Punctual Atom.

Engineering: PWM mode input

Measure the number of pulses in a period of time to find the frequency

Use TIM3_IRQHandler() to interrupt counting the number of PWM wave pulses. At this time, you need to use another timer TIMx as the clock for timing. At this time, use timer 7 as the timing clock and timer 4 to generate the PWM wave.

//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);
  	}
}

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_44333597/article/details/107597740