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.

28027F capture PWM and SCI conflict

Other Parts Discussed in Thread: TMS320F28027F, CONTROLSUITE

My board: TMS320F28027F

I am generating a signal through PWM and I want to measure the period and the duty cycle via capture. I also want to be able to communicate with my device via serial port. For this I have basically thrown together 2 of the examples from the controlSUITE with some modifications (Example_F2802xECap_Capture_Pwm and Example_F2802xSci_Echoback)...

I have 2 (possibly related) problems in my project:

1. I want to measure the signal continuously, without skipping edges (so for example starting at a falling edge, measuring at the rising edge and then measuring at the falling edge and restarting the measurement, without skipping the 2nd falling edge). Is it possible? If yes, what should I do to achieve that?

To solve this I tried all configurations for CAP_setStopWrap(), CAP_enableInt() and CAP_setCapContinuous()/CAP_setCapOneShot() that I thought made sense, with no luck (in the included code I get the data I need, but one period is always skipped).

2. When I set CAP_setStopWrap() and CAP_enableInt() to anything other than CAP_Stop_Wrap_CEVT4 and CAP_Int_Type_CEVT4 respectively, serial communication with the device doesn't work. But for my measurement I essentially only need 2 or 3 events, so setting it to 4 would be a waste. What is the problem here?

Here is my code:

#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/sci.h"

#include "f2802x_common/include/pwm.h"
#include "f2802x_common/include/cap.h"

//
#define EPWM3_TIMER_TBPRD   2000  // Period register
#define EPWM3_INIT_CMPA        0
#define EPWM3_INIT_CMPB     1950

// Prototype statements for functions for serial communication.
void scia_echoback_init(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void scia_msg(char *msg);

// Prototype statements for functions for CAP/PWM.
__interrupt void ecap1_isr(void);
void InitECapture(void);
void InitEPwmTimer(void);

CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
SCI_Handle mySci;

CAP_Handle myCap;
PWM_Handle myPwm;

// Global variables for CAP/PWM
uint32_t  ECap1IntCount;

uint32_t CAP_DATA[] = {0,0,0,0};

void main(void)
{
    uint16_t ReceivedChar;

    CPU_Handle myCpu;
    PLL_Handle myPll;

    // 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));
    mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));

    myPwm = PWM_init((void *)PWM_ePWM3_BASE_ADDR, sizeof(PWM_Obj));
    myCap = CAP_init((void *)CAPA_BASE_ADDR, sizeof(CAP_Obj));

    // Perform basic system initialization
    CLK_enableAdcClock(myClk);
    (*Device_cal)();

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

    // Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
    PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);

    // 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

    // Initialize GPIO (Serial)
    GPIO_setPullUp(myGpio, GPIO_Number_28, GPIO_PullUp_Enable);
    GPIO_setPullUp(myGpio, GPIO_Number_29, GPIO_PullUp_Disable);
    GPIO_setQualification(myGpio, GPIO_Number_28, GPIO_Qual_ASync);
    GPIO_setMode(myGpio, GPIO_Number_28, GPIO_28_Mode_SCIRXDA);
    GPIO_setMode(myGpio, GPIO_Number_29, GPIO_29_Mode_SCITXDA);

    // Initialize GPIO (Capture/PWM)
	GPIO_setPullUp(myGpio, GPIO_Number_4, GPIO_PullUp_Disable);
	GPIO_setMode(myGpio, GPIO_Number_4, GPIO_4_Mode_EPWM3A);

	GPIO_setPullUp(myGpio, GPIO_Number_5, GPIO_PullUp_Enable);
	GPIO_setQualification(myGpio, GPIO_Number_5, GPIO_Qual_Sync);
	GPIO_setMode(myGpio, GPIO_Number_5, GPIO_5_Mode_ECAP1);

    // 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_4, PIE_SubGroupNumber_1,
							  (intVec_t)&ecap1_isr);

    // Setup peripherals for CAP/PWM
    InitEPwmTimer();
    InitECapture();

    // Initialize counters:
	ECap1IntCount = 0;

    // Enable CPU INT4 which is connected to ECAP1-4 INT:
    CPU_enableInt(myCpu, CPU_IntNumber_4);

    // Enable eCAP INTn in the PIE: Group 3 interrupt 1-6
    PIE_enableCaptureInt(myPie);

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

    scia_echoback_init();  // Initialize SCI for echoback
    scia_fifo_init();      // Initialize the SCI FIFO

    for(;;)
    {
        // Wait for inc character
        while(SCI_getRxFifoStatus(mySci) < SCI_FifoStatus_1_Word)
        {
        }

        // Get character
        ReceivedChar = SCI_getData(mySci);
        if(ReceivedChar != '\r'){
        	scia_xmit(ReceivedChar);
        }else{
        	scia_msg("\n\r");
        }

        //Here I decide what to do with the input.
    }
}


// Test 1,SCIA  DLB, 8-bit word, baud rate 0x000F, default, 1 STOP bit, no parity
void scia_echoback_init()
{
    CLK_enableSciaClock(myClk);

    // 1 stop bit,  No loopback
    // No parity,8 char bits,
    // async mode, idle-line protocol
    SCI_disableParity(mySci);
    SCI_setNumStopBits(mySci, SCI_NumStopBits_One);
    SCI_setCharLength(mySci, SCI_CharLength_8_Bits);

    SCI_enableTx(mySci);
    SCI_enableRx(mySci);
    SCI_enableTxInt(mySci);
    SCI_enableRxInt(mySci);

    // SCI BRR = LSPCLK/(SCI BAUDx8) - 1
#if (CPU_FRQ_60MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)194);
#elif (CPU_FRQ_50MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)162);
#elif (CPU_FRQ_40MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)129);
#endif

    SCI_enable(mySci);

    return;
}

// Transmit a character from the SCI
void scia_xmit(int a)
{
    while(SCI_getTxFifoStatus(mySci) != SCI_FifoStatus_Empty)
    {
    }

    SCI_putDataBlocking(mySci, a);
}

void scia_msg(char * msg)
{
    int i;
    i = 0;
    while(msg[i] != '\0')
    {
        scia_xmit(msg[i]);
        i++;
    }
}

// Initialize the SCI FIFO
void scia_fifo_init()
{
    SCI_enableFifoEnh(mySci);
    SCI_resetTxFifo(mySci);
    SCI_clearTxFifoInt(mySci);
    SCI_resetChannels(mySci);
    SCI_setTxFifoIntLevel(mySci, SCI_FifoLevel_Empty);

    SCI_resetRxFifo(mySci);
    SCI_clearRxFifoInt(mySci);
    SCI_setRxFifoIntLevel(mySci, SCI_FifoLevel_4_Words);

    return;
}

void InitEPwmTimer()
{
    CLK_disableTbClockSync(myClk);

    CLK_enablePwmClock(myClk, PWM_Number_3);

    // Setup TBCLK
    PWM_setCounterMode(myPwm, PWM_CounterMode_Up);     // Count up
    PWM_setPeriod(myPwm, EPWM3_TIMER_TBPRD);           // Set timer period
    PWM_disableCounterLoad(myPwm);                     // Disable phase loading
    PWM_setPhase(myPwm, 0x0000);                       // Phase is 0
    PWM_setCount(myPwm, 0x0000);                       // Clear counter
    PWM_setHighSpeedClkDiv(myPwm, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
    PWM_setClkDiv(myPwm, PWM_ClkDiv_by_1);

    // Setup shadow register load on ZERO
    PWM_setShadowMode_CmpA(myPwm, PWM_ShadowMode_Shadow);
    PWM_setShadowMode_CmpB(myPwm, PWM_ShadowMode_Shadow);
    PWM_setLoadMode_CmpA(myPwm, PWM_LoadMode_Zero);
    PWM_setLoadMode_CmpB(myPwm, PWM_LoadMode_Zero);

    // Set Compare values
    PWM_setCmpA(myPwm, EPWM3_INIT_CMPA);    // Set compare A value
    PWM_setCmpB(myPwm, EPWM3_INIT_CMPB);    // Set Compare B value

    // Set Actions
    PWM_setActionQual_CntUp_CmpA_PwmA(myPwm, PWM_ActionQual_Set);      // Set PWM3A on event B, up count
    PWM_setActionQual_CntUp_CmpB_PwmA(myPwm, PWM_ActionQual_Clear);    // Clear PWM3A on event B, up count

    PWM_setActionQual_Zero_PwmB(myPwm, PWM_ActionQual_Toggle);         // Toggle EPWM3B on Zero

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


    CLK_enableTbClockSync(myClk);
}

void InitECapture()
{
    CLK_enableEcap1Clock(myClk);

    CAP_disableInt(myCap, CAP_Int_Type_All);    // Disable all capture interrupts
    CAP_clearInt(myCap, CAP_Int_Type_All);      // Clear all CAP interrupt flags
    CAP_disableCaptureLoad(myCap);              // Disable CAP1-CAP4 register loads
    CAP_disableTimestampCounter(myCap);         // Make sure the counter is stopped

    // Configure peripheral registers
    //CAP_setCapOneShot(myCap);                   // One-shot
    CAP_setCapContinuous(myCap);
    CAP_setStopWrap(myCap, CAP_Stop_Wrap_CEVT3);// Stop at _ events
    CAP_setCapEvtPolarity(myCap, CAP_Event_1, CAP_Polarity_Falling);    // Falling edge
    CAP_setCapEvtPolarity(myCap, CAP_Event_2, CAP_Polarity_Rising);     // Rising edge
    CAP_setCapEvtPolarity(myCap, CAP_Event_3, CAP_Polarity_Falling);    // Falling edge
    //CAP_setCapEvtPolarity(myCap, CAP_Event_4, CAP_Polarity_Rising);     // Rising edge

    CAP_setCapEvtReset(myCap, CAP_Event_1, CAP_Reset_Enable);   // Difference operation
    CAP_setCapEvtReset(myCap, CAP_Event_2, CAP_Reset_Enable);   // Difference operation
    CAP_setCapEvtReset(myCap, CAP_Event_3, CAP_Reset_Enable);   // Difference operation
    //CAP_setCapEvtReset(myCap, CAP_Event_4, CAP_Reset_Enable);   // Difference operation

    CAP_enableSyncIn(myCap);                    // Enable sync in
    CAP_setSyncOut(myCap, CAP_SyncOut_SyncIn);  // Pass through

    CAP_enableCaptureLoad(myCap);

    CAP_enableTimestampCounter(myCap);          // Start Counter
    CAP_rearm(myCap);                           // arm one-shot
    CAP_enableCaptureLoad(myCap);               // Enable CAP1-CAP4 register loads
    CAP_enableInt(myCap, CAP_Int_Type_CEVT3);   // _ events = interrupt
}

__interrupt void ecap1_isr(void)
{
    CAP_DATA[0] = CAP_getCap1(myCap);
	CAP_DATA[1] = CAP_getCap2(myCap);
	CAP_DATA[2] = CAP_getCap3(myCap);
	CAP_DATA[3] = CAP_getCap4(myCap);

    ECap1IntCount++;

    CAP_clearInt(myCap, CAP_Int_Type_CEVT4);
    CAP_clearInt(myCap, CAP_Int_Type_Global);
    CAP_rearm(myCap);

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