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.

CCS/TMS320F28379D: EPWM

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Tool/software: Code Composer Studio

Hello,

           I want to write a program in which PWM signal is generated from EPWM1REGS along with that i can get a output across GPIO14 when 

EPwm1Regs.CMPA.bit.CMPA==1250

and GPIO14 will be lowered when

EPwm1Regs.CMPB.bit.CMPB==1250

but I am getting a constant output across GPIO14 what is the fault in my program and how can I modify the program to get the output across GPIO14 periodically with the compare bit of CMPA and CMPB.

#include "F28x_Project.h"
//
// Defines
//
#define EPWM1_TIMER_TBPRD 2500 // Period register
#define EPWM1_MAX_CMPA 1950
#define EPWM1_MIN_CMPA 25
#define EPWM1_MAX_CMPB 925
#define EPWM1_MIN_CMPB 50

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;

void Gpio_setup (void);
void InitEPwm1Example(void);

__interrupt void epwm1_isr(void);

void main(void)
{
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.

InitGpio();
Gpio_setup ();
//
// enable PWM1, PWM2 and PWM3
//
CpuSysRegs.PCLKCR2.bit.EPWM1=1;
//CpuSysRegs.PCLKCR2.bit.EPWM2=1;
//CpuSysRegs.PCLKCR2.bit.EPWM3=1;

//
// For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
// These functions are in the F2837xD_EPwm.c file
//
InitEPwm1Gpio();
//InitEPwm2Gpio();
//InitEPwm3Gpio();

//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
DINT;

//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//
InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
IER = 0x0000;
IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
InitPieVectTable();


// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//
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

//
// For this example, only initialize the ePWM
//
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;

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

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

//
// Step 4. User specific code, enable interrupts:
//

//
// Enable CPU INT3 which is connected to EPWM1-3 INT:
//
IER |= M_INT3;

//
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
//
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
//PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
//PieCtrlRegs.PIEIER3.bit.INTx3 = 1;

//
// Enable global Interrupts and higher priority real-time debug events:
//
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

//
// Step 5. IDLE loop. Just sit and loop forever (optional):


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

//
// epwm1_isr - EPWM1 ISR
//
__interrupt void epwm1_isr(void)
{
//
// Update the CMPA and CMPB values
//
//update_compare(&epwm1_info);
//GpioDataRegs.GPADAT.bit.GPIO14 = 1;
if(EPwm1Regs.CMPA.bit.CMPA==1250)
{
GpioDataRegs.GPADAT.bit.GPIO14 = 1;

}else
{
GpioDataRegs.GPADAT.bit.GPIO14 = 0;
}

//GpioDataRegs.GPADAT.bit.GPIO14 = 0;

if(EPwm1Regs.CMPB.bit.CMPB==1250)
{
GpioDataRegs.GPADAT.bit.GPIO14 = 0;

}else
{
GpioDataRegs.GPADAT.bit.GPIO14 = 1;
}
//elseif(EPwm1Regs.CMPB.bit.CMPB==1250)
//{
//GpioDataRegs.GPADAT.bit.GPIO14 = 0;
//}
// DELAY_US (100);
//GpioDataRegs.GPADAT.bit.GPIO14 = 0;
//DELAY_US (100);
//
// Clear INT flag for this timer
//
EPwm1Regs.ETCLR.bit.INT = 1;

//
// Acknowledge this interrupt to receive more interrupts from group 3
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}

void InitEPwm1Example()
{
//
// Setup TBCLK
//
EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD; // Set timer period 801 TBCLKs
EPwm1Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
EPwm1Regs.TBCTR = 0x0000; // Clear counter

//
// Set Compare values
//
EPwm1Regs.CMPA.bit.CMPA = 1250;//EPWM1_MIN_CMPA; // Set compare A value
EPwm1Regs.CMPB.bit.CMPB = 1250;//EPWM1_MAX_CMPB; // Set Compare B value

//
// Setup counter mode
//
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

//
// Setup shadowing
//
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

//
// Set actions
//
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up
// count
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A,
// down count

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

//
// 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 = 1250; // Generate INT on 3rd event

}

void Gpio_setup (void)
{
//pull up gpapud
//dir output
//gpio mux1
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0;//GPIO
GpioCtrlRegs.GPADIR.bit.GPIO14 = 1; //output
EDIS;
}

Thank you

Bighnaraj Panda

 

  • Hi,

    I think what you are trying to do here is not correct. The CMPA & CMPB values are already configured as 1250 in initEPWM1Example() and hence the GPIO14 will not toggle as expected by you.

    I think what you intend to do is when the couner value = CMPA, take some action. One option could be to configure interrupt to be triggered when cntr = CMPA & then set/clear GPIO in ISR.

    Also, it's not efficient what you are trying to do here. You can achieve the same on GPIO14 by configuring EPWM8 and configuring the required actions. You can use epwm examples available in C2000Ware for reference.

    Thanks

    Vasudha

  • Vasudha,
    Yes I am trying to generate the interrupt at the value compared to CMPA register so that when the counter is equal to CMPA then inside the interrupt service routine the GPIO14 pin will get high. If I remove the I else logic also then I am getting GPIO14 continuously high but I am trying to make it low when the counter value is at CMPB by the if else statement. But it is not getting lowered.

    How can i assign the value of counter to the interrupt because in my program I have assigned the same value to both the CMPA and interrupt so that interrupt will be generated at the same value of CMPA that is assigned to the counter.

    Thank you
    Bighnaraj Panda
  • Hello,
    Sorry I made a mistake in the if else statement for assigning the gpio values now i have edited it.

    Thank you
    Bighnaraj Panda
  • Hello Vasudha,
    Thank you so much for suggesting, I have edited the program as you suggested still i am not getting any correct result, have rectified accordingly. I am only posting the rectified portion.
    __interrupt void epwm1_isr(void)
    {
    //
    // Update the CMPA and CMPB values
    //
    //update_compare(&epwm1_info);
    //GpioDataRegs.GPADAT.bit.GPIO14 = 1;
    if(EPwm1Regs.TBCTR == 0x4E2)
    {
    GpioDataRegs.GPADAT.bit.GPIO14 = 1;

    }else
    {
    GpioDataRegs.GPADAT.bit.GPIO14 = 0;
    }

    //GpioDataRegs.GPADAT.bit.GPIO14 = 0;

    if(EPwm1Regs.TBCTR == 0x60E)
    {
    GpioDataRegs.GPADAT.bit.GPIO14 = 0;

    }else
    {
    GpioDataRegs.GPADAT.bit.GPIO14 = 1;
    }
    //elseif(EPwm1Regs.CMPB.bit.CMPB==1250)
    //{
    //GpioDataRegs.GPADAT.bit.GPIO14 = 0;
    //}
    // DELAY_US (100);
    //GpioDataRegs.GPADAT.bit.GPIO14 = 0;
    //DELAY_US (100);
    //
    // Clear INT flag for this timer
    //
    EPwm1Regs.ETCLR.bit.INT = 1;

    //
    // Acknowledge this interrupt to receive more interrupts from group 3
    //
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }
    void InitEPwm1Example()
    {
    //
    // Setup TBCLK
    //
    EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD; // Set timer period 801 TBCLKs
    EPwm1Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
    EPwm1Regs.TBCTR = 0x0000; // Clear counter

    //
    // Set Compare values
    //
    EPwm1Regs.CMPA.bit.CMPA = EPWM1_MIN_CMPA; // Set compare A value
    EPwm1Regs.CMPB.bit.CMPB = EPWM1_MAX_CMPB; // Set Compare B value

    //
    // Setup counter mode
    //
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    //
    // Setup shadowing
    //
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //
    // Set actions
    //
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up
    // count
    EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A,
    // down count

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

    //
    // 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_1ST;
    }


    Thank you
    Bighnaraj Panda
  • Hi,
    The above code will also not work as you are checking the counter value in a if statement and will always go to else as the counter is continously running. Why do you need to toggle the GPIO this way?

    Thanks
    Vasudha
  • Hello Vasudha,
    Please suggest me what I shall compare in the if statement to get the logic when the counter value will be equal to CMPA value it should make the GPIO14 register high. I just want to check that if I can make some other pin synchronous with the EPWM1 registers.

    Thank you
    Bighnaraj Panda
  • Hi,

    I think you need to keep checking the required counter value in a while loop. But this should not be done inside ISR. Can try this in main() idle loop.

    Thanks
    Vasudha
  • Hello Vasudha,
    I have written the below while loop inside the main () but it is not giving any result but it was giving a output of 2.5Mhz when if else statement was written inside the main().


    while(EPwm1Regs.TBCTR == 0x4E2)
    {
    GpioDataRegs.GPADAT.bit.GPIO14 = 1;
    }
    while(EPwm1Regs.TBCTR == 0x60E)
    {
    GpioDataRegs.GPADAT.bit.GPIO14 = 0;
    }


    Thank you
    Bighnaraj Panda
  • Hi,

    I should be like below, but I dont think it will be accurate.

    main()
    {
    // Other code
    
    // idle loop
    while(1)
    
    {
    
      if(EPwm1Regs.TBCTR == 0x4E2)
      {
        GpioDataRegs.GPADAT.bit.GPIO14 = 1;
       }
      if(EPwm1Regs.TBCTR == 0x60E)
      {
       GpioDataRegs.GPADAT.bit.GPIO14 = 0;
      }
    }
    }
    

    The better approach would be to set the timer as up counter. Trigger interrupt at ctr = CMPA and toggle GPIO in ISR.

    Thanks

    Vasudha