3、DSP28335输出两路PWM波并设置死区

本文详细介绍了如何在嵌入式系统中使用EPWM(EnhancedPulseWidthModulation)控制占空比,包括向上计数和上下计数模式下配置时基模块、比较模块、动作限定模块以及事件触发模块,以实现不同频率的PWM波形生成。
摘要由CSDN通过智能技术生成

 占空比是指高电平在一个脉冲周期中所占的比例

#include "epwm.h"

//1000k == 1MHz
//1us   -->1Mhz
//10us  -->100KHz
//主频 / 周期值 = 频率

#if PWM_COUNT_UP
//向上计数模式:主频为150MHz,周期值设置为1500,即一个周期有10us,向上计数仅有一个CMP比较值,且为周期的一半
//设置计数值等于0时,输出低电平,大于CMP比较值时输出高电平,即所得占空比为50%,频率为100KHz
void EPwmInit(void)
{
	//1、使能ePWM外设时钟,及失能时基模块时钟,这里在mian函数InitSysCtrl()中完成

	//2、配置对应的GPIO
	InitEPwm6Gpio();

	//3、初始化时基模块TB
	//TB模块用来产生一个时基信号TBCLK,TBCLK通过系统时钟SYSCLKOUT传递过来,同时还需要通过两个时钟分频器进行分频(HSPCLKDIV和CLKDIV)

	//关闭时钟同步输入
	EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
	//关闭相位使能
	EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
	//如果打开时钟同步功能和相位使能功能,那么TBPHS设置的值就会被加载到TBCTR(计数值)里
	EPwm6Regs.TBPHS.half.TBPHS = 0;
	//初始计数值
	EPwm6Regs.TBCTR = 0x0000;
	//设置计数方式
	EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;

	//最高主频 150M
	//时钟分频由两位控制,这里一分频 TBCLK = SYSCLKOUT(HSPCLKDIV * CLKDIV)
	//这里相当于不分频,TBCLK为 150MHz,计数150次,需要1us
	EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
	EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;

	//周期设置为1500,相当于计数1500次,需要10us,周期为10us

    //PWM周期 1500/TBCLK,这里有影子寄存器和活动寄存器
    //当使用影子寄存器更新周期值时,当发生某一个特定时刻时更新
    //当使用活动寄存器时,会立马更新
    EPwm6Regs.TBPRD = 1500;

	//4、初始化比较模块CC
	//影子寄存器模式设置,可以配置为影子寄存器和活动寄存器
	//当配置为活动寄存器时,设置的CMPA值立马起作用
	//当配置为影子寄存器时,当发生某一个特定时刻时,影子寄存器的值传入到活动寄存器中
	EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
	EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

	//要配置影子寄存器工作,需要配置LOADAMODE,当CTR(计数值)为0时加载
	EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
	EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

	//设置比较值

	EPwm6Regs.CMPA.half.CMPA = 750;
    EPwm6Regs.CMPB = 750;

	//5、初始化动作限定模块AQ

    //AQ_NO_ACTION  无动作
    //AQ_CLEAR      置低
    //AQ_SET        置高
    //AQ_TOGGLE     电平翻转

    //ZRO   当计数值 == 0
    //PRD   当计数值 == 周期值
    //CAU   向上计数时,计数值 == CMPA
    //CAD   向下计数时,计数值 == CMPA
    //CBU   向上计数时,计数值 == CMPB
    //CBD   向下计数时,计数值 == CMPB

	EPwm6Regs.AQCTLA.bit.ZRO = AQ_CLEAR;
	EPwm6Regs.AQCTLA.bit.CAU = AQ_SET;

	EPwm6Regs.AQCTLB.bit.ZRO = AQ_CLEAR;
	EPwm6Regs.AQCTLB.bit.CBU = AQ_SET;

	//5、死区
//    DBA_ALL         0x0   ePWMA作为双边延时输入源
//    DBB_RED_DBA_FED 0x1   ePWMB是上升延时输入源 ,epwmA是下降延时输入源
//    DBA_RED_DBB_FED 0x2   ePWMA是上升延时输入源 ,epwmB是下降延时输入源
//    DBB_ALL         0x3   ePWMB是双边沿延时输入源
	EPwm6Regs.DBCTL.bit.IN_MODE = DBA_RED_DBB_FED;
//    DB_ACTV_HI      0x0
//    DB_ACTV_LOC     0x1   //极性选择:A不翻转,B翻转
//    DB_ACTV_HIC     0x2   //极性选择:A翻转,B不翻转
//    DB_ACTV_LO      0x3
	EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;   //极性选择:A不翻转,B翻转
//    DB_DISABLE      0x0   ePWMA 和 ePWMB 都不经过死区
//    DBA_ENABLE      0x1   禁止上升沿延时,使能下降沿延时(一个过下降沿死区,一个直接输出)
//    DBB_ENABLE      0x2   禁止下降沿延时,使能上升沿延时(一个过上升沿死区,一个直接输出)
//    DB_FULL_ENABLE  0x3	ePWMA 和 ePWMB 都经过死区
	EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

	//一个pwm波周期有一个死区时间(一个上升沿延时 或者 一个下降沿延时),这里相当于设置死区时间为1us
	EPwm6Regs.DBFED = 150;
	EPwm6Regs.DBRED = 150;

	//6、初始化事件触发模块
	EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;   //计数值为0时
	EPwm6Regs.ETSEL.bit.INTEN = 1;              //使能中断
	EPwm6Regs.ETPS.bit.INTPRD = ET_1ST;         //设置当事件产生几次时,触发中断

	//7、使能时基计数器时钟
	EALLOW;
	SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
	EDIS;
}

#else
//上下计数模式:主频为150MHz,周期值设置为1500,即理论一个周期有10us,这里上下计数仅仅设置一个CMP比较值,向上计数到最大值时为1500,再由1500向下计数到0,这里才算计数完一次
//设置等于CMP比较值且向上计数时输出高电平,等于CMP比较值且向下计数时输出低电平,即所得占空比为50%,周期为 20us,频率为50KHz
void EPwmInit(void)
{
    //1、使能ePWM外设时钟,及失能时基模块时钟,这里在mian函数InitSysCtrl()中完成

    //2、配置对应的GPIO
    InitEPwm6Gpio();

    //3、初始化时基模块TB
    //TB模块用来产生一个时基信号TBCLK,TBCLK通过系统时钟SYSCLKOUT传递过来,同时还需要通过两个时钟分频器进行分频(HSPCLKDIV和CLKDIV)

    //关闭时钟同步输入
    EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
    //关闭相位使能
    EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;
    //如果打开时钟同步功能和相位使能功能,那么TBPHS设置的值就会被加载到TBCTR(计数值)里
    EPwm6Regs.TBPHS.half.TBPHS = 0;

    //初始计数值
    EPwm6Regs.TBCTR = 0x0000;

    //设置计数方式:上下计数模式
    EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;

    //最高主频 150M
    //时钟分频由两位控制,这里一分频 TBCLK = SYSCLKOUT(HSPCLKDIV * CLKDIV)
    //这里相当于不分频,TBCLK为 150MHz,计数150次,需要1us
    EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
    EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;

    //周期设置为1500,相当于计数1500次,需要10us,周期为10us

    //PWM周期 1500/TBCLK,这里有影子寄存器和活动寄存器
    //当使用影子寄存器更新周期值时,当发生某一个特定时刻时更新
    //当使用活动寄存器时,会立马更新
    EPwm6Regs.TBPRD = 1500;

    //4、初始化比较模块CC
    //影子寄存器模式设置,可以配置为影子寄存器和活动寄存器
    //当配置为活动寄存器时,设置的CMPA值立马起作用
    //当配置为影子寄存器时,当发生某一个特定时刻时,影子寄存器的值传入到活动寄存器中
    EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

    //要配置影子寄存器工作,需要配置LOADAMODE,当CTR为0时加载
    EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //设置比较值

    EPwm6Regs.CMPA.half.CMPA = 750;
    EPwm6Regs.CMPB = 750;

    //5、初始化动作限定模块AQ

    //AQ_NO_ACTION  无动作
    //AQ_CLEAR      置低
    //AQ_SET        置高
    //AQ_TOGGLE     电平翻转

    //ZRO   当计数值 == 0
    //PRD   当计数值 == 周期值
    //CAU   向上计数时,计数值 == CMPA
    //CAD   向下计数时,计数值 == CMPA
    //CBU   向上计数时,计数值 == CMPB
    //CBD   向下计数时,计数值 == CMPB

    EPwm6Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm6Regs.AQCTLA.bit.CAD = AQ_CLEAR;

    EPwm6Regs.AQCTLB.bit.CBU = AQ_SET;
    EPwm6Regs.AQCTLB.bit.CBD = AQ_CLEAR;

    //5、死区
//    DBA_ALL         0x0   ePWMA作为双边延时输入源
//    DBB_RED_DBA_FED 0x1   ePWMB是上升延时输入源 ,epwmA是下降延时输入源
//    DBA_RED_DBB_FED 0x2   ePWMA是上升延时输入源 ,epwmB是下降延时输入源
//    DBB_ALL         0x3   ePWMB是双边沿延时输入源
    EPwm6Regs.DBCTL.bit.IN_MODE = DBA_RED_DBB_FED;
//    DB_ACTV_HI      0x0
//    DB_ACTV_LOC     0x1   //极性选择:A不翻转,B翻转
//    DB_ACTV_HIC     0x2   //极性选择:A翻转,B不翻转
//    DB_ACTV_LO      0x3
    EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;   //极性选择:A不翻转,B翻转
//    DB_DISABLE      0x0   ePWMA 和 ePWMB 都不经过死区
//    DBA_ENABLE      0x1   禁止上升沿延时,使能下降沿延时(一个过下降沿死区,一个直接输出)
//    DBB_ENABLE      0x2   禁止下降沿延时,使能上升沿延时(一个过上升沿死区,一个直接输出)
//    DB_FULL_ENABLE  0x3   ePWMA 和 ePWMB 都经过死区
    EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

    // 向上模式计数 和 向下模式计数 的周期是 上下计数的2倍
    //类似于,上下计数模式实际是有 两个周期,死区设置中,是将死区时间分给了这两个周期,
    //一个pwm波周期有一个死区时间,这里相当于设置死区时间为1us
    EPwm6Regs.DBFED = 150;
    EPwm6Regs.DBRED = 150;

    //6、初始化事件触发模块
    EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;   //计数值为0时
    EPwm6Regs.ETSEL.bit.INTEN = 1;              //使能中断
    EPwm6Regs.ETPS.bit.INTPRD = ET_1ST;         //设置当事件产生几次时,触发中断

    //7、使能时基计数器时钟
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
}
#endif


//设置占空比
void EPwm6A_SetCompare(Uint16 Val)
{
	EPwm6Regs.CMPA.half.CMPA = Val;
}

//设置占空比
void EPwm6B_SetCompare(Uint16 Val)
{
	EPwm6Regs.CMPB = Val;
}
  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在STM32F4中,高级定时器(TIM1-TIM8)具有很多功能和高级特性,包括产生两独立的PWM形。为了确保PWM的稳定性和准确性,需要设置死区时间。 死区时间是指在切换PWM信号的过程中,两个开关之间的时间间隔,避免出现短情况。在STM32F4中,死区时间可以通过预分频系数和ARR自动重装载寄存器进行计算。 首先,确定PWM的频率和周期。假设我们要生成50kHz的PWM形。根据系统的时钟频率和预分频系数,可以计算出TIM的时钟频率。假设系统时钟频率为84MHz,预分频系数为1,则定时器时钟频率为84MHz。 然后,根据所需的PWM频率和定时器时钟频率,计算周期。PWM频率为50kHz,则周期为1/50kHz=20us。 接下来,计算死区时间。死区时间的计算取决于开关管的特性和对电的要求。假设我们需要一个死区时间为1us。 通过以上计算得出周期为20us,死区时间为1us的PWM形。在STM32F4中,可以通过设置死区时间寄存器(BDTR)进行配置。设置CCxP位和CCxNE位来使能正和负两个通道输出。 因此,可以使用以下代码设置定时器的死区时间: ```c TIM_TypeDef *htim; // 定时器指针 // 配置 TIM1 的死区时间 htim = TIM1; htim->BDTR |= TIM_BDTR_MOE | TIM_BDTR_BKP | TIM_BDTR_DTG_1 | TIM_BDTR_DTG_0; htim->CCR1 = 0; // 设置通道1的比较值 htim->CCR2 = 0; // 设置通道2的比较值 ``` 以上代码中,通过修改BDTR寄存器的配置位来设置死区时间。其中MOE位用于使能定时器的主输出,BKP位用于选择断器的极性(负通道输出的极性),DTG位用于设置死区时间的值。 需要注意的是,以上只是简单示例,具体的代码要根据实际需求和定时器设置进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值