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/TMS320F280049C: PWM output has intermittent pulses

Part Number: TMS320F280049C

Tool/software: Code Composer Studio

Dear team,

The customer found that when the PWM output is 0, the PWM output will have intermittent pulses. 

void initEPWM1()
{
    //
    // Set_up TBCLK
    //
    EPWM_setTimeBasePeriod(EPWM1_BASE, EPWM1_TIMER_TBPRD);
    EPWM_setPhaseShift(EPWM1_BASE, 0U);
    EPWM_setTimeBaseCounter(EPWM1_BASE, 0U);

    // Set up counter mode
    EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_disablePhaseShiftLoad(EPWM1_BASE);

    //
    // Set ePWM clock pre-scaler
    //
    EPWM_setClockPrescaler(EPWM1_BASE,
                           EPWM_CLOCK_DIVIDER_4,
                           EPWM_HSCLOCK_DIVIDER_4);

    //
    // Set up shadowing
    //
    EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,
                                         EPWM_COUNTER_COMPARE_A,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,
                                         EPWM_COUNTER_COMPARE_B,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);


    //
    // Set-up compare
    //
    EPWM_setCounterCompareValue(EPWM1_BASE,
                                EPWM_COUNTER_COMPARE_A,
                                EPWM1_MIN_CMPA);
    EPWM_setCounterCompareValue(EPWM1_BASE,
                                EPWM_COUNTER_COMPARE_B,
                                EPWM1_MIN_CMPB);

    //
    // Set actions
    //
    EPWM_setActionQualifierAction(EPWM1_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(EPWM1_BASE,
                                  EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM1_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(EPWM1_BASE,
                                  EPWM_AQ_OUTPUT_B,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);

}

void pump_ctrl(uint16_t pump, uint16_t freq, float32_t ratio)
{
    EPWM_SignalParams *signalParams;
    uint32_t base;
    float32_t tbClkInHz = 0.0F;
    uint16_t tbPrdVal = 0U, cmpAVal = 0U, cmpBVal = 0U;

    switch (pump)
    {
        case 0:
            base = EPWM1_BASE;
            signalParams = &pwmSignal1;
            signalParams->dutyValA = ratio;
            if(ratio != 0.0)
                neg_pump1_status = 1;
            else
                neg_pump1_status = 0;
            break;
        case 1:
            base = EPWM1_BASE;
            signalParams = &pwmSignal1;
            signalParams->dutyValB = ratio;
            if(ratio != 0.0)
                  neg_pump2_status = 1;
              else
                  neg_pump2_status = 0;
            break;
        case 2:
            base = EPWM2_BASE;
            signalParams = &pwmSignal2;
            signalParams->dutyValA = ratio;
            if(ratio != 0.0)
                  pos_pump_status = 1;
              else
                  pos_pump_status = 0;
            break;
    }

    signalParams->freqInHz = freq;

    //
    // Calculate TBCLK, TBPRD and CMPx values to be configured for
    // achieving desired signal
    //
    tbClkInHz = ((float32_t)signalParams->sysClkInHz /
                (1U << (uint16_t)signalParams->tbClkDiv));

    if(signalParams->tbCtrMode == EPWM_COUNTER_MODE_UP)
    {
        tbPrdVal = (uint16_t)((tbClkInHz / signalParams->freqInHz) - 1.0f);
        cmpAVal = (uint16_t)((float32_t)signalParams->dutyValA *
                             (tbPrdVal + 1U));
        cmpBVal = (uint16_t)((float32_t)signalParams->dutyValB *
                             (tbPrdVal + 1U));
    }
    else if(signalParams->tbCtrMode == EPWM_COUNTER_MODE_DOWN)
    {
        tbPrdVal = (uint16_t)((tbClkInHz / signalParams->freqInHz) - 1.0f);
        cmpAVal = (uint16_t)((tbPrdVal + 1U) -
                       ((float32_t)signalParams->dutyValA * (tbPrdVal + 1U)));
        cmpBVal = (uint16_t)((tbPrdVal + 1U) -
                       ((float32_t)signalParams->dutyValB * (tbPrdVal + 1U)));
    }
    else if((signalParams->tbCtrMode == EPWM_COUNTER_MODE_UP_DOWN))
    {

        tbPrdVal = (uint16_t)(tbClkInHz / (2.0f * signalParams->freqInHz));
            cmpBVal = (uint16_t)(((float32_t)tbPrdVal -
                                         ((float32_t)(signalParams->dutyValB *
                                          tbPrdVal))) + 0.5f);
            cmpAVal = (uint16_t)(((float32_t)tbPrdVal -
                                         ((float32_t)(signalParams->dutyValA *
                                          tbPrdVal))) + 0.5f);
    }

    //
    // Configure TBPRD value
    //
    EPWM_setTimeBasePeriod(base, tbPrdVal);

    //
    // Set Compare values
    //
    EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A,
                                cmpAVal);
    EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_B,
                                cmpBVal);



//    ++counterA;
//    if(counterA < epwm1Info.epwmMaxCompA)
//    {
//        epwm1Info.epwmCompA = counterA;
//    }
//    else
//    {
//        counterA = epwm1Info.epwmMinCompA;
//    }
//
//    ++counterB;
//    if(counterB < epwm1Info.epwmMaxCompB)
//    {
//        epwm1Info.epwmCompB = counterB;
//    }
//    else
//    {
//        counterB = epwm1Info.epwmMinCompB;
//    }
//    updataCompare(&epwm1Info);
}

void main()
{
    //
    // Disable sync(Freeze clock to PWM as well)
    //
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    DINT;

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();
    

    //
    // Enable sync and clock to PWM
    //
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;

    // Disable pin locks and enable internal pullups.
    Device_initGPIO();
    // Set up GPIOs
    setupGPIO();

    //
    // Configuring ePWM module for desired frequency and duty
    //
    EPWM_configureSignal(EPWM1_BASE, &pwmSignal1);
    EPWM_configureSignal(EPWM2_BASE, &pwmSignal2);


    pump_ctrl(POS_PUMP, 0, 0);
}

The characteristics of this pulse are related to the timing duration set by CPUtimer1. The longer the timer duration, the greater the pulse width. The timer program is as follows

void initTimerInterrupt(void)
{
    // ISRs for each CPU Timer interrupt
    // Timer0 for led
    // Timer1 for PPG ADC
    Interrupt_register(INT_TIMER0, &cpuTimer0ISR);
    Interrupt_register(INT_TIMER1, &cpuTimer1ISR);


    // Initializes the cpu timers
    initCPUTimers();
//    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);


    // Configure CPU-Timer0 to interrupt every second: 1 second period(1 uSeconds)
    // Configure CPU-Timer1 to interrupt every msecond
    configCPUTimer(CPUTIMER0_BASE, DEVICE_SYSCLK_FREQ, 1000000);
    configCPUTimer(CPUTIMER1_BASE, DEVICE_SYSCLK_FREQ, 100);


    // To ensure precise timing, use write-only instruction to write to the
    // entire register, Therefore, if any of the configuration bits are changed
    // in configCPUTimer and initCPUTimers, the below settings must also be updated.
    CPUTimer_enableInterrupt(CPUTIMER0_BASE);
    CPUTimer_enableInterrupt(CPUTIMER1_BASE);

    // Enables CPU int1.
    // Enable TINT0 in the PIE: Group 1 interrupt 7
    Interrupt_enable(INT_TIMER0);
    Interrupt_enable(INT_TIMER1);


    //Starts CPU-Timer 0
    CPUTimer_startTimer(CPUTIMER0_BASE);
    CPUTimer_startTimer(CPUTIMER1_BASE);


}

//
// initCPUTimers - This function initializes all three CPU timers
// to a known state.
//
void initCPUTimers(void)
{
    // Initialize timer period to maximum
    CPUTimer_setPeriod(CPUTIMER0_BASE, 0XFFFFFFFF);
    CPUTimer_setPeriod(CPUTIMER1_BASE, 0XFFFFFFFF);


    // Initialize pre-scale counter to divide by 1(SYSCLKOUT)
    CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);
    CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);


    // Make sure timer is stopped
    CPUTimer_stopTimer(CPUTIMER0_BASE);
    CPUTimer_stopTimer(CPUTIMER1_BASE);


    // Reload all counter register with period value
    CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
    CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);


    // Reset interrupt counter
    cpuTimer0IntCount = 0;
    cpuTimer1IntCount = 0;

}

//
// configCPUTimer - This function initializes the selected timer to the
// period specified by the "freq" and "period" parameters. The "freq" is
// entered as Hz and the period in uSeconds. The timer is held in the stopped
// state after configuration.
//
void configCPUTimer(uint32_t cpuTimer, float freq, float period)
{
    uint32_t temp;

    // Initialize timer period
    temp = (uint32_t)(freq / 1000000 * period);
    CPUTimer_setPeriod(cpuTimer, temp);

    // Set pre-scale counter to divide by 1 (SYSCLKOUT)
    CPUTimer_setPreScaler(cpuTimer, 0);

    // Initializes timer control register. The timer is stopped, reloaded,
    // free run disabled, and interrupt enabled.
    // Additionally, the free and soft bits are set
    CPUTimer_stopTimer(cpuTimer);
    CPUTimer_reloadTimerCounter(cpuTimer);
    CPUTimer_setEmulationMode(cpuTimer, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
    CPUTimer_enableInterrupt(cpuTimer);

    // Resets interrupt counters for the cpuTimer
    if(cpuTimer == CPUTIMER0_BASE)
    {
        cpuTimer0IntCount = 0;
    }
    else if(cpuTimer == CPUTIMER1_BASE)
    {
        cpuTimer1IntCount = 0;
    }
}
//
// cpuTimer1ISR - Counter for CpuTimer1
//
__interrupt void cpuTimer1ISR(void)
{
    // Save IER register on stack
//    volatile uint16_t tempPIEIER = HWREGH(PIECTRL_BASE + PIE_O_IER1);

    // Set the global and group priority to allow CPU interrupts
    // with higher priority
//    IER |= M_INT2;
//    IER &= MINT2;
//    HWREGH(PIECTRL_BASE + PIE_O_IER1);

    // Enable Interrupts
    Interrupt_clearACKGroup(0xFFFFU);
//    __asm(" NOP");
//    EINT;
    cpuTimer1IntCount++;
    // Insert ISR code here
    if(IRLED_flip == 0)
    {
        IRLED_flip = 1;
        if(init_count<5000)//按照1000us定时,2000次相当于4s长度的数据
        {
            ++init_count;
        }
//        //使IRLED关闭
//        SPI_transmit(mySPI0_BASE, 0X0000);
//        SPI_transmit(mySPI0_BASE, 0X3000);

        // 测试DAC输出与阀输出的关系
        DAC_VALVE_RELATIVE_TEST();
    }
    else
    {
        IRLED_flip = 0;
//        //使IRLED打开
//        SPI_transmit(mySPI0_BASE, 0X0800);
//        SPI_transmit(mySPI0_BASE, 0X3800);
    }

//    ADC_flag = 1;

    // Disable interrupts and restore register saved;
//    DINT;
//    HWREGH(PIECTRL_BASE + PIE_O_IER1) = tempPIEIER;

//    // Add ISR to Trace
//    traceISR[traceISRIndex % TRACE_SIZE] = 0x00D0;
//    traceISRIndex++;
}

Please help.