我们在tms320上处理PWM模块

下午好。前一段时间,我读到有人想更深入地研究关于mk tms320f28xxx上的ePWM模块的问题,因此我决定为什么不撰写有关此主题的文章,在其中我将尝试使用tms320f28335的示例详细介绍该模块。 ...



EPWM模块功能



  • EpwmA epwmB输出可以用作:

    • 单边操作
    • 双边缘对称操作
    • 双边缘不对称运算
  • 死区时间可以配置
  • 可以配置TZ事件,并且可以设置HI和LO输出的逻辑状态。
  • 可以配置ADC的中断事件或SOC事件。


让我们更接近主要模块:ePWM模块由什么组成以及与之连接的内容。







从图中可以看出,ePWM模块中没有很多块。因此,考虑每个模块负责什么并从信号开始是有意义的。



  • EPWMxA和EPWMxB信号可能是最明显的输出信号。正常逻辑状态为HI或LO,具体取决于配置输出动作的方式
  • TZ1 — TZ6 — . , , , . , EPWMxA EPWMxB . , , - , , . . , .
  • EPWMxSYNCI EPWMxSYNCO — , , .
  • EPWMxSOCA和EPWMxSOCB信号-此处的所有内容都比名字更清晰。这些事件可以设置ADC的SOC事件。
  • EPWMxTZINT和EPWMxINT信号-此处是TZ以及与PWM本身相关的事件的中断事件,例如,在PWM周期产生中断。


现在让我们进入



时基(TB)模块-该模块负责每个ePWM模块的事件时间。我们不会介绍该模块的所有设置,我认为足够注意计数器有3种工作模式这一事实:



  • 上下计数模式
  • 递增计数模式
  • 倒数模式






通过设置TBCLKSYNC



计数器比较(CC)模块,还有一个定时器同步设置-通过它我们可以设置占空比。

动作限定符(AQ)模块-通过它可以配置事件的状态。对于输出,您可以配置以下操作:



  • 设为HI状态
  • 设置为LO状态
  • 执行状态反转
  • 没事做


死区子模块(DB)模块-该模块可用于设置PWM通道的死区。晶体管键不会立即切换对任何人来说都不是秘密,并且为了避免上半桥键没有时间关闭而下半键已经打开的情况,它们设置了切换到HI状态和更早切换到LO状态的延迟。



防区分区子模块(TZ)模块-如上所述,此模块与处理紧急情况相关联。在这里,我们可以选择4个动作之一。



  • 设为HI状态
  • 设置为LO状态
  • 设置高阻状态
  • 没事做


触发TZ模块动作的事件可以由软件和硬件触发。另外,提供了一个中断调用。



现在,让我们从言语转向实践。



首先,您需要为替代的epwm功能配置GPIO



EALLOW;
//  pull-up
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0x000;  
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0x000;  
//  GPIO   EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0x001;   
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0x001;  

EDIS;


接下来,当我们已经配置了GPIO时,我们可以继续进行不同的设置。要配置PWM操作,您需要决定我们想要得到什么。让我们从TBCLK频率开始。它由以下公式确定:



ŤC大号ķ=小号ÿ小号C大号ķØüŤ/H小号PC大号ķd一世V×C大号ķd一世V



在这里,您需要注意一个事实,即CLKDIV默认为1,而HSPCLKDIV则不同,默认为2。这是要记住的,因为有时人们会忘记它。当将程序加载到RAM中时,通常分别为HSPCLKDIV = 1,不会立即注意到此问题。



我们已经决定了TBCLK的时钟频率。但是我们必须选择计数器如何为我们工作。通过衰退,通过增加,也许通过这种方式,为此,您需要配置适当的寄存器,例如:



 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
 


将来,没有人会被宏吓倒,我们将确定它们的来源。这些定义在名为DSP2833x_EPwm_defines.h的文件中定义。



然后,您需要确定我们的GPIO对达到某些TBCTR值的反应。有足够多的选择。它们显示在下表中:







然后,您需要确定我们想要从端口A和B获得什么行为,即,我们希望它们彼此连接或能够独立工作。如果我们希望端口A作为主端口,那么我们只需为它写下操作(例如,向上计数的情况):



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


如果我们想要第二个端口的独立性,则添加:



    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
    EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;


有关设置的更多详细信息,您只需要参考上图即可,AQCTLA寄存器比表中显示的要多一些,这不会改变图片,但是仅介绍有关计数器达到所需值的详细信息,例如,当计数时顶部或倒数。有关这些位的更简要信息,可以在系统.h文件的剪切中找到。



struct AQCTL_BITS {            // bits   description
    Uint16 ZRO:2;              // 1:0    Action Counter = Zero
    Uint16 PRD:2;              // 3:2    Action Counter = Period
    Uint16 CAU:2;              // 5:4    Action Counter = Compare A up
    Uint16 CAD:2;              // 7:6    Action Counter = Compare A down
    Uint16 CBU:2;              // 9:8    Action Counter = Compare B up
    Uint16 CBD:2;              // 11:10  Action Counter = Compare B down
    Uint16 rsvd:4;             // 15:12  reserved
};


如果我们有2个独立工作的ePWM端口,并且想要设置死区时间,则需要将寄存器设置为所需状态,例如:



EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;


现在我们已经确定了外围设备的描述,我们可以继续进行具体的示例。



在计数模式下配置ePWM



这是一个没有停滞时间并且端口A和端口B独立工作的示例。当A处于活动状态时,B处于非活动状态。



	EPwm1Regs.TBPRD = 150000 / 5; 	// .  150 / 5000 
    //   50%
    EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD / 2;	
    EPwm1Regs.TBPHS.half.TBPHS = 0; 
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; 
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; 
    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; 
    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; 
    EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR;
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm1Regs.AQCTLB.bit.PRD = AQ_SET;
    EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR;


在示波器上,您可以看到获得的结果:







现在您可以尝试添加空载时间,为此,我们添加:



    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm1Regs.DBCTL.all = BP_ENABLE + POLSEL_ACTIVE_HI_CMP;	//  db 
    EPwm1Regs.DBFED = 300;	//   = 150 * 2 = 300
    EPwm1Regs.DBRED = 300; 


根据以下公式,空载时间的计算方法与频率相同:

d=ŤC大号ķdË一种dŤ一世Ë;



现在我们按照自己想要的方式得到了死时间,







如果我们需要解开端口A和端口B怎么办?这也会发生。这里的一切都很简单。我们回到第一个示例,删除最后4行,并将每个占空比写入以下寄存器。



    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
    EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;
    EPwm1Regs.CMPA.half.CMPA 	= EPwm1Regs.TBPRD / 2;	//   50%  
    EPwm1Regs.CMPB	= EPwm1Regs.TBPRD / 3;	//   33%  


现在我们有这样一张照片。您可以分别设置每个通道的占空比。







对于衰减模式,一切都大致相同。上下模式中的倒数有所不同。匀场频率使用以下公式计算:

ŤP[Rd=ŤC大号ķ/2Fpw



死区时间也是如此。



也许没有考虑的唯一重要的事情是TZ设置,现在让我们更详细地介绍这个模块。



要以编程方式触发警报事件,只需配置以下寄存器即可:



    EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
    EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO;


可以使用以下命令来调用和重置PWM警报:



    // 
    EALLOW;
        EPwm1Regs.TZFRC.bit.OST = 0x001;
    EDIS;
	
    //  
    EALLOW;
	EPwm1Regs.TZCLR.bit.OST = 0x0001;
    EDIS;


如果要在硬件中调用TZ信号,则一切都变得更加容易,通过TZSEL寄存器设置所需的TZ,但除此之外,我们需要将GPIO配置为TZ。



结论



如果有人觉得这篇文章有趣,那么我可以以或多或少的加速方式写几篇文章。我打算考虑使用can模块,我想对它进行dma,也许我还将与他们的库一起从ti撰写有关IQMath的小文章。



All Articles