This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: 修改EPWM位置到4,5,6無法產生波形,程式码是用范例程式epwm_up_aq_cpu01

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

#include "F28x_Project.h"

#define EPWM1_TIMER_TBPRD  2000  // Period register
#define EPWM1_MAX_CMPA     1950
#define EPWM1_MIN_CMPA       50
#define EPWM1_MAX_CMPB     1950
#define EPWM1_MIN_CMPB       50

#define EPWM2_TIMER_TBPRD  2000  // Period register
#define EPWM2_MAX_CMPA     1950
#define EPWM2_MIN_CMPA       50
#define EPWM2_MAX_CMPB     1950
#define EPWM2_MIN_CMPB       50

#define EPWM3_TIMER_TBPRD  2000  // Period register
#define EPWM3_MAX_CMPA      950
#define EPWM3_MIN_CMPA       50
#define EPWM3_MAX_CMPB     1950
#define EPWM3_MIN_CMPB     1050

#define EPWM_CMP_UP           1
#define EPWM_CMP_DOWN         0

typedef struct
{
    volatile struct EPWM_REGS *EPwmRegHandle;
    Uint16 EPwm_CMPA_Direction;
    Uint16 EPwm_CMPB_Direction;
    Uint16 EPwmTimerIntCount;
    Uint16 EPwmMaxCMPA;
    Uint16 EPwmMinCMPA;
    Uint16 EPwmMaxCMPB;
    Uint16 EPwmMinCMPB;
}EPWM_INFO;

EPWM_INFO epwm1_info;
EPWM_INFO epwm2_info;
EPWM_INFO epwm3_info;

void InitEPwm1Example(void);
void InitEPwm2Example(void);
void InitEPwm3Example(void);
__interrupt void epwm1_isr(void);
__interrupt void epwm2_isr(void);
__interrupt void epwm3_isr(void);
void update_compare(EPWM_INFO*);

void main(void)
{

    InitSysCtrl();


    CpuSysRegs.PCLKCR2.bit.EPWM4=1;
    CpuSysRegs.PCLKCR2.bit.EPWM5=1;
    CpuSysRegs.PCLKCR2.bit.EPWM6=1;

    InitEPwm4Gpio();
    InitEPwm5Gpio();
    InitEPwm6Gpio();

    DINT;

    InitPieCtrl();

    IER = 0x0000;
    IFR = 0x0000;

    InitPieVectTable();

    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.EPWM1_INT = &epwm1_isr;
    PieVectTable.EPWM2_INT = &epwm2_isr;
    PieVectTable.EPWM3_INT = &epwm3_isr;
    EDIS;   // This is needed to disable write to EALLOW protected registers

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    InitEPwm1Example();
    InitEPwm2Example();
    InitEPwm3Example();

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;

    IER |= M_INT3;

    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
    PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
    PieCtrlRegs.PIEIER3.bit.INTx3 = 1;

    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

    for(;;)
    {
        asm ("  NOP");
    }
}

__interrupt void epwm1_isr(void)
{
    
    update_compare(&epwm1_info);

    
    EPwm1Regs.ETCLR.bit.INT = 1;

    
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}

__interrupt void epwm2_isr(void)
{
    
    update_compare(&epwm2_info);

    
    EPwm2Regs.ETCLR.bit.INT = 1;

    
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}


__interrupt void epwm3_isr(void)
{
    
    update_compare(&epwm3_info);

    
    EPwm3Regs.ETCLR.bit.INT = 1;

    
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}


void InitEPwm1Example()
{
   
   EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
   EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;       // Set timer period
   EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
   EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
   EPwm1Regs.TBCTR = 0x0000;                  // Clear counter
   EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;   // Clock ratio to SYSCLKOUT
   EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2;

   
   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.CMPA.bit.CMPA = EPWM1_MIN_CMPA;     // Set compare A value
   EPwm1Regs.CMPB.bit.CMPB = EPWM1_MIN_CMPB;     // Set Compare B value

   
   EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
   EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A,
                                                 // up count

   EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;            // Set PWM1B on Zero
   EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;          // Clear PWM1B on event B,
                                                 // up count

   
   EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
   EPwm1Regs.ETSEL.bit.INTEN = 1;                // Enable INT
   EPwm1Regs.ETPS.bit.INTPRD = ET_3RD;           // Generate INT on 3rd event

   
   epwm1_info.EPwm_CMPA_Direction = EPWM_CMP_UP; // Start by increasing
                                                 // CMPA & CMPB
   epwm1_info.EPwm_CMPB_Direction = EPWM_CMP_UP;
   epwm1_info.EPwmTimerIntCount = 0;             // Zero the interrupt counter
   epwm1_info.EPwmRegHandle = &EPwm1Regs;        // Set the pointer to the
                                                 // ePWM module
   epwm1_info.EPwmMaxCMPA = EPWM1_MAX_CMPA;      // Setup min/max
                                                 // CMPA/CMPB values
   epwm1_info.EPwmMinCMPA = EPWM1_MIN_CMPA;
   epwm1_info.EPwmMaxCMPB = EPWM1_MAX_CMPB;
   epwm1_info.EPwmMinCMPB = EPWM1_MIN_CMPB;
}


void InitEPwm2Example()
{
   
   EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
   EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD;       // Set timer period
   EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
   EPwm2Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
   EPwm2Regs.TBCTR = 0x0000;                  // Clear counter
   EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;   // Clock ratio to SYSCLKOUT
   EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV2;

   
   EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
   EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
   EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
   EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

   
   EPwm2Regs.CMPA.bit.CMPA = EPWM2_MIN_CMPA;      // Set compare A value
   EPwm2Regs.CMPB.bit.CMPB = EPWM2_MAX_CMPB;      // Set Compare B value

   
   EPwm2Regs.AQCTLA.bit.PRD = AQ_CLEAR;            // Clear PWM2A on Period
   EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;              // Set PWM2A on event A,
                                                   // up count

   EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR;            // Clear PWM2B on Period
   EPwm2Regs.AQCTLB.bit.CBU = AQ_SET;              // Set PWM2B on event B,
                                                   // up count

   
   EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;       // Select INT on Zero event
   EPwm2Regs.ETSEL.bit.INTEN = 1;                  // Enable INT
   EPwm2Regs.ETPS.bit.INTPRD = ET_3RD;             // Generate INT on 3rd event

   
   epwm2_info.EPwm_CMPA_Direction = EPWM_CMP_UP;   // Start by increasing CMPA
   epwm2_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN; // and decreasing CMPB
   epwm2_info.EPwmTimerIntCount = 0;               // Zero the interrupt
                                                   // counter
   epwm2_info.EPwmRegHandle = &EPwm2Regs;          // Set the pointer to the
                                                   // ePWM module
   epwm2_info.EPwmMaxCMPA = EPWM2_MAX_CMPA;        // Setup min/max
                                                   // CMPA/CMPB values
   epwm2_info.EPwmMinCMPA = EPWM2_MIN_CMPA;
   epwm2_info.EPwmMaxCMPB = EPWM2_MAX_CMPB;
   epwm2_info.EPwmMinCMPB = EPWM2_MIN_CMPB;
}


void InitEPwm3Example(void)
{
   /
   EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
   EPwm3Regs.TBPRD = EPWM3_TIMER_TBPRD;       // Set timer period
   EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
   EPwm3Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
   EPwm3Regs.TBCTR = 0x0000;                  // Clear counter
   EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;   // Clock ratio to SYSCLKOUT
   EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;

   
   EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
   EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
   EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
   EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

   
   EPwm3Regs.CMPA.bit.CMPA = EPWM3_MIN_CMPA;  // Set compare A value
   EPwm3Regs.CMPB.bit.CMPB = EPWM3_MAX_CMPB;  // Set Compare B value

   
   EPwm3Regs.AQCTLA.bit.CAU = AQ_SET;         // Set PWM3A on event B, up count
   EPwm3Regs.AQCTLA.bit.CBU = AQ_CLEAR;       // Clear PWM3A on event B,
                                              // up count
   EPwm3Regs.AQCTLB.bit.ZRO = AQ_TOGGLE;      // Toggle EPWM3B on Zero

   //
   // Interrupt where we will change the Compare Values
   //
   EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;  // Select INT on Zero event
   EPwm3Regs.ETSEL.bit.INTEN = 1;             // Enable INT
   EPwm3Regs.ETPS.bit.INTPRD = ET_3RD;        // Generate INT on 3rd event

   
   epwm3_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
   epwm3_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN;

   
   epwm3_info.EPwmTimerIntCount = 0;
   epwm3_info.EPwmRegHandle = &EPwm3Regs;
   epwm3_info.EPwmMaxCMPA = EPWM3_MAX_CMPA;
   epwm3_info.EPwmMinCMPA = EPWM3_MIN_CMPA;
   epwm3_info.EPwmMaxCMPB = EPWM3_MAX_CMPB;
   epwm3_info.EPwmMinCMPB = EPWM3_MIN_CMPB;
}

void update_compare(EPWM_INFO *epwm_info)
{
   //
   // Every 10'th interrupt, change the CMPA/CMPB values
   //
   if(epwm_info->EPwmTimerIntCount == 10)
   {
       epwm_info->EPwmTimerIntCount = 0;

       
       if(epwm_info->EPwm_CMPA_Direction == EPWM_CMP_UP)
       {
           if(epwm_info->EPwmRegHandle->CMPA.bit.CMPA < epwm_info->EPwmMaxCMPA)
           {
              epwm_info->EPwmRegHandle->CMPA.bit.CMPA++;
           }
           else
           {
              epwm_info->EPwm_CMPA_Direction = EPWM_CMP_DOWN;
              epwm_info->EPwmRegHandle->CMPA.bit.CMPA--;
           }
       }

       //
       // If we were decreasing CMPA, check to see if
       // we reached the min value.  If not, decrease CMPA
       // else, change directions and increase CMPA
       //
       else
       {
           if(epwm_info->EPwmRegHandle->CMPA.bit.CMPA == epwm_info->EPwmMinCMPA)
           {
              epwm_info->EPwm_CMPA_Direction = EPWM_CMP_UP;
              epwm_info->EPwmRegHandle->CMPA.bit.CMPA++;
           }
           else
           {
              epwm_info->EPwmRegHandle->CMPA.bit.CMPA--;
           }
       }

       
       if(epwm_info->EPwm_CMPB_Direction == EPWM_CMP_UP)
       {
           if(epwm_info->EPwmRegHandle->CMPB.bit.CMPB < epwm_info->EPwmMaxCMPB)
           {
              epwm_info->EPwmRegHandle->CMPB.bit.CMPB++;
           }
           else
           {
              epwm_info->EPwm_CMPB_Direction = EPWM_CMP_DOWN;
              epwm_info->EPwmRegHandle->CMPB.bit.CMPB--;
           }
       }

       
       else
       {
           if(epwm_info->EPwmRegHandle->CMPB.bit.CMPB ==
              epwm_info->EPwmMinCMPB)
           {
              epwm_info->EPwm_CMPB_Direction = EPWM_CMP_UP;
              epwm_info->EPwmRegHandle->CMPB.bit.CMPB++;
           }
           else
           {
              epwm_info->EPwmRegHandle->CMPB.bit.CMPB--;
           }
       }
   }
   else
   {
      epwm_info->EPwmTimerIntCount++;
   }

   return;
}

//
// End of file
//

  • 你好,工程师将在工作时间回复你的问题。

  • 你好,请问你的问题是已经解决了吗?

  • 问题我已经解决了,结果是发现板子有问题,还有再询问一下要如何只让EPWMB显示而A不显示呢? 我看到是说能用TZ模块进行封波不知道是否正确,有其他范例程式的推荐吗? 谢谢

  • 是指PWMB输出正常的波形而PWMA只输出低电压或者高电压吗?

    如果是的话是可以通过TZ模块来进行封波,例程可以参考以下路径:C:\ti\c2000\C2000Ware_4_01_00_00\driverlib\f2837xd\examples\cpu1\epwm

    其中的example1就是。

  • 是的,类似控制三相马达,上臂导通下臂不导通的概念

  • 马达控制的话情况就多了,你说的“上臂导通下臂不导通”是用死区实现的,之前说的“只让EPWMB显示而A不显示”用AQ模块或者TZ模块都可以,AQ实现的话机动性更高,TZ模块的话更保险。

  • 而我试着开启AQ模块,使用了(AHC)功能,但波行只能显示A相,无法查看B相波形,这样是否正确?

    void InitEPwm1Example()
    {
       //
       // Setup TBCLK
       //
       EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
       EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;       // Set timer period
       EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
       EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
       EPwm1Regs.TBCTR = 0x0000;                  // Clear counter
       EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;   // Clock ratio to SYSCLKOUT
       EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2;
    
       //
       // Setup shadow register load on ZERO
       //
       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;
    
       //
       // Set Compare values
       //
       EPwm1Regs.CMPA.bit.CMPA = EPWM1_MIN_CMPA;     // Set compare A value
       EPwm1Regs.CMPB.bit.CMPB = EPWM1_MIN_CMPB;     // Set Compare B value
    
       //
       // Set actions
       //
       EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
       EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A,
                                                     // up count
    
       EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;            // Set PWM1B on Zero
       EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;          // Clear PWM1B on event B,
                                                     // up count
       EPwm1Regs.AQSFRC.all = 0x0000;      // Action-qualifier s/w force register
       EPwm1Regs.AQCSFRC.all = 0x0000;     // Action-qualifier continuous s/w force register
       EPwm1Regs.DBCTL.all = 0x002B;           
       EPwm1Regs.DBRED.all = DeadTime;         // rising edge delay
       EPwm1Regs.DBFED.all = DeadTime;         // falling edge delay
    
       //
       // Interrupt where we will change the Compare Values
       //
       EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
       EPwm1Regs.ETSEL.bit.INTEN = 1;                // Enable INT
       EPwm1Regs.ETPS.bit.INTPRD = ET_3RD;           // Generate INT on 3rd event
    } 

  • 不是这个位,这个位是用来输出互补的。

    不行还是参考例程用TZ模块做吧,TZ模块比较简单,也比较靠谱。

  • 好的谢谢,我只是好奇(AHC)这功能为什么只能显示EPWMA,是因为互补的关系吗?

  • 不是,互补输出的话PWMA/B的输出是会呈现互补的情况,不会“无法查看”。

    不知道你说的“无法查看B相波形”是指B相波形是保持低/高电平,还是B相根本没有输出?

  •    EPwm1Regs.DBCTL.all = 0x002B;           
    

    按造你所说的我设定DBCTL这功能应该是能看到B相波形

    下图则是开启DBCTL功能所呈现的波形图

    而下图是无开启DBCTL功能所呈现的波形图

  • 你好,这个波形有点尴尬,主要是你的PWMA的占空比太大了。

    图2可以理解是正常的PWMB互补输出

    但是图1的波形有可能是使能了PWMB互补输出+死区的情况,导致PWMB的高电位被死区占了,也可能是AQ的设置使PWMB输出低电位(因为DB模块对输出的影响在AQ模块之后,所以DB模块的设置会影响最后PWM的输出,见下图)。

    所以,如果是使能了DB模块的情况下,设置AQ寄存器控制PWMB封波的话是会失效的。

    同样的原因,如果要控制PWMA封波的话只能通过设置TZ模块的方式实现

  • 确实跟您所说的状况一样,我设的占空比接近100%导致它跟死区时间重叠无法出现波形,非常感谢你帮我解惑

  • 客气了,方便的话点一下确认答案摁扭,方便其他工程师参考

  • 奥,刚看到你一开始就确认过答案了,感谢感谢