[XMG助力国产生态]
@XMGroupe.
本文介绍使用MC3172实现基于三角波调制的带死区的互补PWM产生方法。
常见的PWM调制方法有三种,即向上计数 向下计数 向上-向下计数,此demo使用向上向下计数,MC3172的PWM输出方法比较灵活,能够满足不同的需要,但是其每个timer只有四个compare让其使用存在一定局限,希望下一代能够增加到至少六个compare。
1.初始化
此demo使用timer3的P0和P1当作EPWM的P和N。
#define Dead_time 1000 //死区时间设置
void Pwm_Init(u32 timer_sel,u32 Arr,u32 Cmp)
{
INTDEV_SET_CLK_RST(timer_sel,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK));
TIMER_SET_OVERRIDE_GPIO(timer_sel,(TIMER_P3_OVERRIDE_GPIO|TIMER_P3_PULL_UP| \
TIMER_P2_OVERRIDE_GPIO|TIMER_P2_PULL_UP| \
TIMER_P1_OVERRIDE_GPIO|TIMER_P1_PULL_UP| \
TIMER_P0_OVERRIDE_GPIO|TIMER_P0_PULL_UP) \
);
TIMER_SET_OUTPUT_EN(timer_sel,(TIMER_P0_OUTPUT_ENABLE |TIMER_P1_OUTPUT_ENABLE |TIMER_P2_OUTPUT_ENABLE |TIMER_P3_OUTPUT_ENABLE| \
));
//分为四组,做两对互补
TIMER_SET_OUT_PORT(timer_sel,(TIMER_P0_IS_COMPARER0|TIMER_P1_IS_COMPARER1| \
TIMER_P2_IS_COMPARER2|TIMER_P3_IS_COMPARER3| \
));
TIMER_SET_COMPARER_MODE(timer_sel,(TIMER_COMPARER3_NOT_FORCE|TIMER_COMPARER2_NOT_FORCE|TIMER_COMPARER1_NOT_FORCE|TIMER_COMPARER0_NOT_FORCE));
//下面四条用于控制频率
TIMER_SET_MAIN_CNT_BEGIN_VALUE0(timer_sel,TIMER_MAIN_CNT_COUNT_UP,0);
TIMER_SET_MAIN_CNT_END_VALUE0(timer_sel,Arr);
TIMER_SET_MAIN_CNT_BEGIN_VALUE1(timer_sel,TIMER_MAIN_CNT_COUNT_DOWN,Arr);
TIMER_SET_MAIN_CNT_END_VALUE1(timer_sel,0);
TIMER_SET_CMD(timer_sel,TIMER_CMD_RESTART);
TIMER_SET_COMPARER0_VALUE0_0(timer_sel,TIMER_COMPARER_OUTPUT1,0x00);
TIMER_SET_COMPARER0_VALUE0_1(timer_sel,TIMER_COMPARER_OUTPUT0,(Cmp-Dead_time));
TIMER_SET_COMPARER0_VALUE1_0(timer_sel,TIMER_COMPARER_OUTPUT1,(Cmp-Dead_time));
TIMER_SET_COMPARER0_VALUE1_1(timer_sel,TIMER_COMPARER_OUTPUT0,0x00);
TIMER_SET_COMPARER1_VALUE0_0(timer_sel,TIMER_COMPARER_OUTPUT0,0x00);
TIMER_SET_COMPARER1_VALUE0_1(timer_sel,TIMER_COMPARER_OUTPUT1,(Cmp+Dead_time));
TIMER_SET_COMPARER1_VALUE1_0(timer_sel,TIMER_COMPARER_OUTPUT0,(Cmp+Dead_time));
TIMER_SET_COMPARER1_VALUE1_1(timer_sel,TIMER_COMPARER_OUTPUT1,0x00);
TIMER_SET_CMD(timer_sel,TIMER_CMD_RUN);
}
需要注意,采用向上-向下计数方法,其PWM频率为 系统频率/ARR/2,因此死区时间为 Dead_time * (2/系统频率)
此实验采用200M外部有源晶振,因此demo的PWM频率为100 000 000/ARR,死区时间为 1000*10ns = 10us(正常不需要这么大,此处为了验证EPWM在大占空比时能否实现强制输出)。
2.占空比修改函数
void Set_PWM_Duty(u32 timer_sel,u32 Arr,float Duty1)
{
static u8 flag_set = 0;
static float Duty_old = 0.0;
static u32 Compare_old = 0;
static u32 Cmp = 0;
u32 CNT = 0;
u8 RP = 0;
if(Duty_old != Duty1)
{
Duty_old = Duty1;
Cmp = (u32)(Duty1*Arr);
flag_set = 0x80; //最高位置1,开启修改占空比
}
if((flag_set & 0x80) != 0) //判断最高位
{
if((Cmp > Dead_time)&&((Arr - Cmp) > Dead_time)) //P、N脚正常输出
{
TIMER_SET_COMPARER_MODE(timer_sel,(TIMER_COMPARER3_NOT_FORCE|TIMER_COMPARER2_NOT_FORCE| \
TIMER_COMPARER1_NOT_FORCE|TIMER_COMPARER0_NOT_FORCE));
}
else if(Cmp <= Dead_time) //P脚关闭输出
{
TIMER_SET_COMPARER_MODE(timer_sel,(TIMER_COMPARER3_NOT_FORCE|TIMER_COMPARER2_NOT_FORCE| \
TIMER_COMPARER1_NOT_FORCE|TIMER_COMPARER0_FORCE0));
}
else if(((Arr - Cmp) <= Dead_time)) //N脚关闭输出
{
TIMER_SET_COMPARER_MODE(timer_sel,(TIMER_COMPARER3_NOT_FORCE|TIMER_COMPARER2_NOT_FORCE| \
TIMER_COMPARER1_FORCE0|TIMER_COMPARER0_NOT_FORCE));
}
TIMER_GET_MAIN_CNT_ALL(timer_sel,CNT,RP);
if(RP == 1) //不在规则区0,修改规则区0
{
if(flag_set == 0x80) //第一次修改
{
flag_set = 0x81; //修改标志位,规则0 次序1
//compare0
TIMER_SET_COMPARER0_VALUE0_0(timer_sel,TIMER_COMPARER_OUTPUT1,0x00);
TIMER_SET_COMPARER0_VALUE0_1(timer_sel,TIMER_COMPARER_OUTPUT0,(Cmp-Dead_time));
//compare1
TIMER_SET_COMPARER1_VALUE0_0(timer_sel,TIMER_COMPARER_OUTPUT0,0x00);
TIMER_SET_COMPARER1_VALUE0_1(timer_sel,TIMER_COMPARER_OUTPUT1,(Cmp+Dead_time));
}
else if(flag_set == 0x82) //第二修改
{
flag_set = 0; //修改标志位
//compare0
TIMER_SET_COMPARER0_VALUE0_0(timer_sel,TIMER_COMPARER_OUTPUT1,0x00);
TIMER_SET_COMPARER0_VALUE0_1(timer_sel,TIMER_COMPARER_OUTPUT0,(Cmp-Dead_time));
//compare1
TIMER_SET_COMPARER1_VALUE0_0(timer_sel,TIMER_COMPARER_OUTPUT0,0x00);
TIMER_SET_COMPARER1_VALUE0_1(timer_sel,TIMER_COMPARER_OUTPUT1,(Cmp+Dead_time));
}
}
//修改规则1区
else
{
if(flag_set == 0x80) //第一修改
{
flag_set = 0x82; //修改标志位,规则1 次序1
//compare0
TIMER_SET_COMPARER0_VALUE1_0(timer_sel,TIMER_COMPARER_OUTPUT1,(Cmp-Dead_time));
TIMER_SET_COMPARER0_VALUE1_1(timer_sel,TIMER_COMPARER_OUTPUT0,0x00);
//compare1
TIMER_SET_COMPARER1_VALUE1_0(timer_sel,TIMER_COMPARER_OUTPUT0,(Cmp+Dead_time));
TIMER_SET_COMPARER1_VALUE1_1(timer_sel,TIMER_COMPARER_OUTPUT1,0x00);
}
else if(flag_set == 0x81) //第二修改,修改结束
{
flag_set = 0; //修改标志位
//compare0
TIMER_SET_COMPARER0_VALUE1_0(timer_sel,TIMER_COMPARER_OUTPUT1,(Cmp-Dead_time));
TIMER_SET_COMPARER0_VALUE1_1(timer_sel,TIMER_COMPARER_OUTPUT0,0x00);
//compare1
TIMER_SET_COMPARER1_VALUE1_0(timer_sel,TIMER_COMPARER_OUTPUT0,(Cmp+Dead_time));
TIMER_SET_COMPARER1_VALUE1_1(timer_sel,TIMER_COMPARER_OUTPUT1,0x00);
}
}
}
}
上面的函数实现了EPWM的占空比设置和死区校验,防止出现占空比寄存数大于死区时间时输出高电平的现象。
3.输出PWM
输出的PWM如下图所示
在其占空比较小时,其输出电平被强制输出为低电平
离线
大佬真是啥都会
离线