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.

TBCTR not counting



I was testing pwm of my own code to test the CMPA register. However, I found that my TBCTR is not counting and hence my interrupt did not occur at all. Most of the codes I copy and paste following the sequence from the examples. I did some  changes with the code to make it look cleaner.

#include "DSP28x_Project.h" // Device Headerfile and Examples Include File

#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/pwm.h"
#include "f2802x_common/include/wdog.h"

// Configure which ePWM timer interrupts are enabled at the PIE level:
// 1 = enabled, 0 = disabled
#define PWM1_INT_ENABLE 1

// Configure the period for each timer
#define PWM1_TIMER_TBPRD 0x1387
#define EPWM1_MAX_CMPA 0x09C4
#define EPWM1_MIN_CMPA 0x09C4

// Prototype statements for functions found within this file.
interrupt void epwm1_timer_isr(void);

void initSys();
void initHandler();
void InitEPwmTimer(void);
void initGPIO();

CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
PWM_Handle myPwm1;
CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;

void main(void)
{
initHandler();
initSys();

//Select the internal oscillator 1 as the clock source
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

// Setup the PLL for x12 /2 which will yield 60Mhz = 10Mhz * 12 / 2
PLL_setup(myPll, PLL_Multiplier_1, PLL_DivideSelect_ClkIn_by_1);

// Disable the PIE and all interrupts
PIE_disable(myPie);
PIE_disableAllInts(myPie);
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);

// If running from flash copy RAM only functions to RAM
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

// Setup a debug vector table and enable the PIE
PIE_setDebugIntVectorTable(myPie);
PIE_enable(myPie);

// Register interrupt handlers in the PIE vector table
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_3, PIE_SubGroupNumber_1, (intVec_t)&epwm1_timer_isr);

InitEPwmTimer();

// Enable CPU INT3 which is connected to EPWM1-6 INT
CPU_enableInt(myCpu, CPU_IntNumber_3);

// Enable EPWM INTn in the PIE: Group 3 interrupt 1-6
PIE_enablePwmInt(myPie, PWM_Number_1);

// Enable global Interrupts and higher priority real-time debug events
CPU_enableGlobalInts(myCpu);
CPU_enableDebugInt(myCpu);

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

}
}

void initHandler()
{
// Initialize all the handles needed for this application
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
myPwm1 = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
}

void initSys()
{
// Perform basic system initialization
WDOG_disable(myWDog);
CLK_enableAdcClock(myClk);
(*Device_cal)();
CLK_disableAdcClock(myClk);
}

void InitEPwmTimer()
{

CLK_enablePwmClock(myClk, PWM_Number_1);

PWM_setPeriod(myPwm1, PWM1_TIMER_TBPRD);
PWM_setCounterMode(myPwm1, PWM_CounterMode_Up); // Count up
PWM_disableCounterLoad(myPwm1); // Disable phase loading
PWM_setPhase(myPwm1, 0x0000); // Phase is 0
PWM_setHighSpeedClkDiv(myPwm1, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
PWM_setClkDiv(myPwm1, PWM_ClkDiv_by_1);

PWM_setShadowMode_CmpA(myPwm1, PWM_ShadowMode_Shadow);
PWM_setLoadMode_CmpA(myPwm1, PWM_LoadMode_Zero);

PWM_setCmpA(myPwm1, EPWM1_MIN_CMPA); // Set compare A value

PWM_setActionQual_Zero_PwmA(myPwm1, PWM_ActionQual_Clear); // Clear PWM1A on Zero
PWM_setActionQual_CntUp_CmpA_PwmA(myPwm1, PWM_ActionQual_Set); // Set PWM1A on event A, up count

// Interrupt where we will change the Compare Values
PWM_setIntMode(myPwm1, PWM_IntMode_CounterEqualZero); // Select INT on Zero event
PWM_enableInt(myPwm1); // Enable INT
PWM_setIntPeriod(myPwm1, PWM_IntPeriod_FirstEvent); // Generate INT on 3rd event

}

void initGPIO()
{
GPIO_setPullUp(myGpio, GPIO_Number_0, GPIO_PullUp_Enable);
GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
GPIO_setLow(myGpio, GPIO_Number_0);
}

// Interrupt routines uses in this example:
interrupt void epwm1_timer_isr(void)
{
DELAY_US(500000);
GPIO_toggle(myGpio, GPIO_Number_0);
// Clear INT flag for this timer
PWM_clearIntFlag(myPwm1);

// Acknowledge this interrupt to receive more interrupts from group 3
PIE_clearInt(myPie, PIE_GroupNumber_3);
}

Thanks in advance for helping

  • Hi GIP,

    I did some  changes with the code to make it look cleaner.

    Can you please highlight the changes made? Also, please refer the same example code for spotting the error. TBCTR - not incrementing means there's some config issue or improper initialization.

    Regards,

    Gautam

  • #include "DSP28x_Project.h" // Device Headerfile and Examples Include File
    #include "f2802x_common/include/clk.h"
    #include "f2802x_common/include/flash.h"
    #include "f2802x_common/include/gpio.h"
    #include "f2802x_common/include/pie.h"
    #include "f2802x_common/include/pll.h"
    #include "f2802x_common/include/pwm.h"
    #include "f2802x_common/include/wdog.h"
    // Configure which ePWM timer interrupts are enabled at the PIE level:
    // 1 = enabled, 0 = disabled
    #define PWM1_INT_ENABLE 1
    // Configure the period for each timer
    #define PWM1_TIMER_TBPRD 0x1387
    #define EPWM1_MAX_CMPA 0x09C4
    #define EPWM1_MIN_CMPA 0x09C4
    // Prototype statements for functions found within this file.
    interrupt void epwm1_timer_isr(void);
    void initSys();
    void initHandler();
    void InitEPwmTimer(void);
    void initGPIO();
    CLK_Handle myClk;
    FLASH_Handle myFlash;
    GPIO_Handle myGpio;
    PIE_Handle myPie;
    PWM_Handle myPwm1;
    CPU_Handle myCpu;
    PLL_Handle myPll;
    WDOG_Handle myWDog;
    void main(void)
    {
    initHandler();
    initSys();
     
    //Select the internal oscillator 1 as the clock source
    CLK_setOscSrc(myClk, CLK_OscSrc_Internal);
    // Setup the PLL for x12 /2 which will yield 60Mhz = 10Mhz * 12 / 2
    PLL_setup(myPll, PLL_Multiplier_1, PLL_DivideSelect_ClkIn_by_1);
    // Disable the PIE and all interrupts
    PIE_disable(myPie);
    PIE_disableAllInts(myPie);
    CPU_disableGlobalInts(myCpu);
    CPU_clearIntFlags(myCpu);
    // If running from flash copy RAM only functions to RAM
    #ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif
    // Setup a debug vector table and enable the PIE
    PIE_setDebugIntVectorTable(myPie);
    PIE_enable(myPie);
    // Register interrupt handlers in the PIE vector table
    PIE_registerPieIntHandler(myPie, PIE_GroupNumber_3, PIE_SubGroupNumber_1, (intVec_t)&epwm1_timer_isr);
    InitEPwmTimer();
    // Enable CPU INT3 which is connected to EPWM1-6 INT
    CPU_enableInt(myCpu, CPU_IntNumber_3);
    // Enable EPWM INTn in the PIE: Group 3 interrupt 1-6
    PIE_enablePwmInt(myPie, PWM_Number_1);
    // Enable global Interrupts and higher priority real-time debug events
    CPU_enableGlobalInts(myCpu);
    CPU_enableDebugInt(myCpu);
    for(;;) {
    asm(" NOP");
    }
    }
    // This is moved into a function and handler are made into global variables
    // Programming wise should not be any problem since the changes is only from local to global vairables
    void initHandler()
    {
    // Initialize all the handles needed for this application
    myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
    myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
    myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
    myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
    myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
    myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
    myPwm1 = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
    myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
    }
    //This initiallization was in main but nothing major is affecting PWM
    void initSys()
    {
    // Perform basic system initialization
    WDOG_disable(myWDog);
    CLK_enableAdcClock(myClk);
    (*Device_cal)();
    CLK_disableAdcClock(myClk);
    }
    void InitEPwmTimer()
    {
    CLK_enablePwmClock(myClk, PWM_Number_1);
    PWM_setPeriod(myPwm1, PWM1_TIMER_TBPRD);
    PWM_setCounterMode(myPwm1, PWM_CounterMode_Up); // Count up
    //Phase loading is disabled as it is not used in the function
    PWM_disableCounterLoad(myPwm1); // Disable phase loading
    PWM_setPhase(myPwm1, 0x0000); // Phase is 0
    //Maintain the CLK frequency in 10Mhz
    PWM_setHighSpeedClkDiv(myPwm1, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
    PWM_setClkDiv(myPwm1, PWM_ClkDiv_by_1);
    //Activate shadow register to load CmpA value when counter is zero
    PWM_setShadowMode_CmpA(myPwm1, PWM_ShadowMode_Shadow);
    PWM_setLoadMode_CmpA(myPwm1, PWM_LoadMode_Zero);
    PWM_setCmpA(myPwm1, EPWM1_MIN_CMPA); // Set compare A value
    //Changes here is to readjust so that when PWM not yet reach CMPA value it will stay low until TBCTR = CMPA
    PWM_setActionQual_Zero_PwmA(myPwm1, PWM_ActionQual_Clear); // Clear PWM1A on Zero
    PWM_setActionQual_CntUp_CmpA_PwmA(myPwm1, PWM_ActionQual_Set); // Set PWM1A on event A, up count
    //Interrupt mode is set when TBCTR = 0 and to generate interrupt every TBCTR = TBPRD
    PWM_setIntMode(myPwm1, PWM_IntMode_CounterEqualZero); // Select INT on Zero event
    PWM_enableInt(myPwm1); // Enable INT
    PWM_setIntPeriod(myPwm1, PWM_IntPeriod_FirstEvent); // Generate INT on 3rd event
    }
    //Initialize GPIO so that it blinks whenever interrupt occur.
    void initGPIO()
    {
    GPIO_setPullUp(myGpio, GPIO_Number_0, GPIO_PullUp_Enable);
    GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
    GPIO_setLow(myGpio, GPIO_Number_0);
    }
    //LED on GPIO 0 will blink whenever interrupt occur to show that PWM is working according to desire
    // Interrupt routines uses in this example:
    interrupt void epwm1_timer_isr(void)
    {
    DELAY_US(500000);
    GPIO_toggle(myGpio, GPIO_Number_0);
    // Clear INT flag for this timer
    PWM_clearIntFlag(myPwm1);
    // Acknowledge this interrupt to receive more interrupts from group 3
    PIE_clearInt(myPie, PIE_GroupNumber_3);
    }
    The highlights in red are the changes that I made. Furthermore, Im still a starter for C2000 and I am looking for enable register for pwm as the project im working on require multiple use of PWM at the same time on different PWM. Hence having a switch for PWM will be very much helpful as I will be controlling multiple hobby servo at the same time.
    Thanks in advance,
    Gregorius
  • I am using EPWMUP example and EPWMTimerInt example as my reference program