国赛12届中有测量拓展板PULS1频率,PWM1、PWM2占空比。
一、原理图以及两个通道的实际频率
PWM1的实际频率大概在11KHz左右
PWM2实际频率在1.1KHz左右
二、CubeMX配置
对于单通道双边沿测量占空比,由于PWM1频率太大,当占空比太大或太小时测不准,我觉得可以在CubeMX中加入数字滤波。当然,这仅仅是拙见,如果有更好的方法,请在评论区留言。
使用Both Edges测量占空比,测量三次来获得占空比Duty = (Value1-Value0)/(Value2-Value0);
第一次:上升沿触发,获得第一次的值Value0,触发方式改为下降沿;
第二次:下降沿触发,获得第二次的值Value1,触发方式改为上升沿;
第三次:上升沿触发,获得第三次的值Value2,寄存器清零,Duty = (Value1-Value0)/(Value2-Value0)。
三、代码
IC_PWM.C
#include "ic_pwm.h"
#include "tim.h"
uint32_t PULS1_Fre = 0;
struct IC_Dat TIM3Dat = {0.0f,0,{0,0,0}}, TIM17Dat = {0.0f,0,{0,0,0}};
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//输入捕获中断回调函数
{
if(htim == &htim2 )//PULS1
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//来自于通道2
{
uint32_t n = 0;
n = HAL_TIM_ReadCapturedValue (htim ,TIM_CHANNEL_2 );
__HAL_TIM_SetCounter (htim ,0);
PULS1_Fre = 1000000 / n;
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_2 );//重新启动
}
}
else if(htim == &htim3)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//来自于通道1
{
//Edge:0(rise)->1(fall)->2(rise),三次捕获完成
if((TIM3Dat.Edge % 2) == 0)//上升沿
{
TIM3Dat.Value [TIM3Dat.Edge] = HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_1 );
if(TIM3Dat.Edge == 2)//三次捕获完成
{
TIM3Dat.Duty = (TIM3Dat.Value[1] * 1.0f - TIM3Dat.Value[0])/(TIM3Dat.Value[2] - TIM3Dat.Value[0]);
TIM3Dat.Edge = 0;
__HAL_TIM_SetCounter (htim ,0);//清零
__HAL_TIM_SET_CAPTUREPOLARITY (htim ,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//重新设置为上升沿捕获
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_1 );
}
else
{
TIM3Dat.Edge = 1;
__HAL_TIM_SET_CAPTUREPOLARITY (htim ,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);//设置为下降沿捕获
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_1 );
}
}
else//下降沿
{
TIM3Dat.Value [TIM3Dat.Edge] = HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_1 );
TIM3Dat.Edge = 2;
__HAL_TIM_SET_CAPTUREPOLARITY (htim ,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//重新设置为上升沿捕获
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_1 );
}
}
}
else if(htim == &htim17 )
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//来自于通道1
{
//Edge:0(rise)->1(fall)->2(rise),三次捕获完成
if((TIM17Dat.Edge % 2) == 0)//上升沿
{
TIM17Dat.Value [TIM17Dat.Edge] = HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_1 );
if(TIM17Dat.Edge == 2)//三次捕获完成
{
TIM17Dat.Duty = (TIM17Dat.Value[1] * 1.0f - TIM17Dat.Value[0])/(TIM17Dat.Value[2] - TIM17Dat.Value[0]);
TIM17Dat.Edge = 0;
__HAL_TIM_SetCounter (htim ,0);//清零
__HAL_TIM_SET_CAPTUREPOLARITY (htim ,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//重新设置为上升沿捕获
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_1 );
}
else
{
TIM17Dat.Edge = 1;
__HAL_TIM_SET_CAPTUREPOLARITY (htim ,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);//设置为下降沿捕获
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_1 );
}
}
else//下降沿
{
TIM17Dat.Value [TIM17Dat.Edge] = HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_1 );
TIM17Dat.Edge = 2;
__HAL_TIM_SET_CAPTUREPOLARITY (htim ,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//重新设置为上升沿捕获
HAL_TIM_IC_Start_IT (htim ,TIM_CHANNEL_1 );
}
}
}
}
IC_PWM.h
#ifndef __IC_PWM_H
#define __IC_PWM_H
#include "stm32g4xx_hal.h"
struct IC_Dat{
float Duty;
uint8_t Edge;
uint32_t Value[3];
};
#endif
main函数的功能函数
/*******************************************LCD*****************************/
char LCD_BUF[30];
/*************************************IC************************************/
extern uint32_t PULS1_Fre;
extern struct IC_Dat TIM3Dat, TIM17Dat;
void LCD_Display(void )/***********************************LCD*************************/
{
sprintf (LCD_BUF ,"PULS1:%dHz ",PULS1_Fre);
LCD_DisplayStringLine (Line1 ,(uint8_t *)LCD_BUF);
sprintf (LCD_BUF ,"PWM1_Duty:%.1f ",TIM3Dat.Duty*100.0f );
LCD_DisplayStringLine (Line2 ,(uint8_t *)LCD_BUF);
sprintf (LCD_BUF ,"PWM2_Duty:%.1f ",TIM17Dat.Duty*100.0f);
LCD_DisplayStringLine (Line3 ,(uint8_t *)LCD_BUF);
}
四、功能演示
改良后测量占空比