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/LAUNCHXL-F28027: Developing code that uses ePWM and SCI (Serial Communication) in conjunction.

Part Number: LAUNCHXL-F28027

Tool/software: Code Composer Studio

Hello everyone,

I am having a similar issue to the thread here: https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/655110, but I see this was not resolved with a conclusive solution. My end goal is to recieve frequency and phase from serial communication and then use that information to configure the ePWM module to produce a waveform with that frequency and phase. I have combined codes that were based on the TI examples SCI_Echoback (for serial communication) and epwm_updown_aq (ePWM) for the C2000 LaunchXL-F28027, but they do not work together. It seems that my interrupts are interfering with my serial communication code, and characters are being received from serial communication, but they are not being stored in my character array (msgArrray). Can you please help me?  

Below is my code:

//###########################################################################
//
// FILE: Example_2802xSci_Echoback.c
//
// TITLE: f2802x Device SCI Echoback.
//
// ASSUMPTIONS:
//
// This program requires the f2802x header files.
// As supplied, this project is configured for "boot to SARAM" operation.
//
// Connect the SCI-A port to a PC via a transciever and cable.
// The PC application 'hypterterminal' can be used to view the data
// from the SCI and to send information to the SCI. Characters received
// by the SCI port are sent back to the host.
//
// As supplied, this project is configured for "boot to SARAM"
// operation. The 2802x Boot Mode table is shown below.
// For information on configuring the boot mode of an eZdsp,
// please refer to the documentation included with the eZdsp,
//
// $Boot_Table
// While an emulator is connected to your device, the TRSTn pin = 1,
// which sets the device into EMU_BOOT boot mode. In this mode, the
// peripheral boot modes are as follows:
//
// Boot Mode: EMU_KEY EMU_BMODE
// (0xD00) (0xD01)
// ---------------------------------------
// Wait !=0x55AA X
// I/O 0x55AA 0x0000
// SCI 0x55AA 0x0001
// Wait 0x55AA 0x0002
// Get_Mode 0x55AA 0x0003
// SPI 0x55AA 0x0004
// I2C 0x55AA 0x0005
// OTP 0x55AA 0x0006
// Wait 0x55AA 0x0007
// Wait 0x55AA 0x0008
// SARAM 0x55AA 0x000A <-- "Boot to SARAM"
// Flash 0x55AA 0x000B
// Wait 0x55AA Other
//
// Write EMU_KEY to 0xD00 and EMU_BMODE to 0xD01 via the debugger
// according to the Boot Mode Table above. Build/Load project,
// Reset the device, and Run example
//
// $End_Boot_Table
//
// DESCRIPTION:
//
//
// This test receives and echo-backs data through the SCI-A port.
//
// 1) Configure hyperterminal:
// Use the included hyperterminal configuration file SCI_96.ht.
// To load this configuration in hyperterminal: file->open
// and then select the SCI_96.ht file.
// 2) Check the COM port.
// The configuration file is currently setup for COM1.
// If this is not correct, disconnect Call->Disconnect
// Open the File-Properties dialog and select the correct COM port.
// 3) Connect hyperterminal Call->Call
// and then start the 2802x SCI echoback program execution.
// 4) The program will print out a greeting and then ask you to
// enter a character which it will echo back to hyperterminal.
//
//
// Watch Variables:
// LoopCount for the number of characters sent
// ErrorCount
//
//
//###########################################################################
// $TI Release: F2802x Support Library v3.03.00.00 $
// $Release Date: Mon Dec 23 17:27:16 IST 2019 $
// $Copyright:
// Copyright (C) 2009-2019 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################

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

// Typedefs - for ePWM
//
typedef struct
{
volatile struct EPWM_REGS *EPwmRegHandle;
uint16_t EPwm_CMPA_Direction;
uint16_t EPwm_CMPB_Direction;
uint16_t EPwmTimerIntCount;
uint16_t EPwmMaxCMPA;
uint16_t EPwmMinCMPA;
uint16_t EPwmMaxCMPB;
uint16_t EPwmMinCMPB;
} EPWM_INFO;

// Function Prototypes - Serial Comm
//
void scia_echoback_init(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void scia_msg(char *msg);

// Function prototypes - ePWM
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*);

//
// Globals - ePWM
EPWM_INFO epwm1_info;
EPWM_INFO epwm2_info;
EPWM_INFO epwm3_info;

//
// Globals - Serial Comm
//
uint16_t LoopCount = 0;
uint16_t ErrorCount;
uint16_t charCount;
uint16_t j;
uint16_t k = 0;
uint16_t n = 0;
uint16_t i = 0;
uint16_t entryCount = 0;
Uint32 freqInt = 0;
Uint16 phaseInt = 0;
char freqChar[7] = "000000\0";
char phaseChar[4] = "\0\0\0\0";
char ptr[7] = "345665\0";
Uint16 ReceivedChar;
char msgArray[13] = "000000000000\0";


//
// Defines to configure the period for each timer
// Refer to f2802x_sysctrl.c, f2802x_EPwm.h and f2802x_examples.h for more detail on system clock values
//
#define EPWM1_TIMER_TBPRD 86 // Period register TBPRD = 0.5 * fTBCLK/fPWM = 0.5 * 60MHz clock on F28027 / 350kHz frequency desired = 85.7143 ~ 86 , 850kHz --> 35.29
// 1 MHz: 0.5 * 60 MHz / 1 MHz = 30, 600 kHz: 0.5 * 60 MHz / 600 kHz = 50
#define EPWM1_MAX_CMPA 43
#define EPWM1_MIN_CMPA 43 // Compare Register CMPA = (100 - Duty Cycle) * TBPRD --> 50% Duty Cycle: (100%-50%) * 86 = 0.5 * 86 = 43
#define EPWM1_MAX_CMPB 43
#define EPWM1_MIN_CMPB 43

#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

//
// Defines that keep track of which way the compare value is moving
//
#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0

//
// Main
//
void main(void)
{

char *msg;


//
// WARNING: Always ensure you call memcpy before running any functions from
// RAM InitSysCtrl includes a call to a RAM based function and without a
// call to memcpy first, the processor will go "into the weeds"
//
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

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

//
// Step 2. Initialize GPIO:
// This example function is found in the f2802x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
//InitGpio(); Skipped for this example

//
// For Serial Comm, only init the pins for the SCI-A port.
// This function is found in the f2802x_Sci.c file.
// For ePWM just init GPIO pins for ePWM1, ePWM2, ePWM3
// These functions are in the f2802x_EPwm.c file
//
InitEPwm1Gpio();
InitEPwm2Gpio();
InitEPwm3Gpio();
InitSciaGpio();

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

//
// Initialize 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 f2802x_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 f2802x_DefaultIsr.c.
// This function is found in f2802x_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;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;

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

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

// Step 4. Initialize all the Device Peripherals
// Not required for this example
//

// Step 5.1 User specific code for ePWM, Enabling 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 real-time interrupt DBGM

// Step 5.2 User specific code for Serial Communication
//--------------------------------------------------------------

LoopCount = 0;
ErrorCount = 0;

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

msg = "\r\nPlease Enter Frequency and Phase in the Following Format w/ Proper # of Digits (Frequency (X)/Phase (#)): <XXXXXX,###>\n\0";
scia_msg(msg);

for(;;)
{
//
// Wait for inc character
//
while(SciaRegs.SCIFFRX.bit.RXFFST !=1)
{
//
// wait for XRDY =1 for empty state
//
}

// Receive Character in Buffer
ReceivedChar = SciaRegs.SCIRXBUF.all;

// Look for opening character '<' of transmitted message
// If new message is being transmitted (entryCount = 1 means the first message has sent), clear old messages stored
// Also clear frequency and phase information stored
if(ReceivedChar == '<' && entryCount > 0) {
LoopCount = 0;
memset(msgArray, 0, sizeof msgArray);
freqInt = 0;
phaseInt = 0;
freqChar[7] = "\0\0\0\0\0\0\0"; // new
phaseChar[4] = "\0\0\0\0"; // new
}

// Store a character in the Receive Buffer
scia_xmit(ReceivedChar);
msgArray[LoopCount] = ReceivedChar;
LoopCount++;

// Look for closing character '>' of transmitted message
// Once entire message is received, extract frequency and phase info from message
if(ReceivedChar == '>') { // was if(ReceivedChar == '>')
while(msgArray[j] != ',') {
if (msgArray[j] == '<') {
j++;
}

else {
freqChar[k] = msgArray[j];
j++;
k++;
}
}

k = 0;

while(msgArray[j] != '>') {
if (msgArray[j] == ',') {
j++;
}

else {
phaseChar[k] = msgArray[j];
j++;
k++;
}
}

j = 0;
k = 0;

// Once you have extracted frequency & phase info
// Convert this info from data type char to int
// We will use the frequency & phase integers for ePWM
for (n = 0; freqChar[n] != '\0'; n++) {
freqInt = freqInt * 10 + freqChar[n] - '0';
}

for (n = 0; phaseChar[n] != '\0'; n++) {
phaseInt = phaseInt * 10 + phaseChar[n] - '0';
}
n = 0;

}
entryCount++;
}
}

// eWPM Code - Use ePWM up-down & dead band tutorials
// Want to get phase & frequency and then send that to the ePWM module to generate a waveform

void
scia_echoback_init()
{
// scia_echoback_init - Test 1,SCIA DLB, 8-bit word, baud rate 0x000F, default
// 1 STOP bit, no parity
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
//

//
// 1 stop bit, No loopback, No parity, 8 char bits, async mode,
// idle-line protocol
//
SciaRegs.SCICCR.all =0x0007;

//
// enable TX, RX, internal SCICLK, Disable RX ERR, SLEEP, TXWAKE
//
SciaRegs.SCICTL1.all =0x0003;
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =1;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;

//
// SCI BRR = LSPCLK/(SCI BAUDx8) - 1
//
#if (CPU_FRQ_60MHZ)
SciaRegs.SCIHBAUD = 0x0000; // 9600 baud @LSPCLK = 15MHz(60 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x00C2;
#elif (CPU_FRQ_50MHZ)
SciaRegs.SCIHBAUD = 0x0000; // 9600 baud @LSPCLK = 12.5 MHz(50 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x00A1;
#elif (CPU_FRQ_40MHZ)
SciaRegs.SCIHBAUD = 0x0000; // 9600 baud @LSPCLK = 10MHz(40 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x0081;
#endif

SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
}

//
// scia_xmit - Transmit a character from the SCI
//
void
scia_xmit(int a)
{
while (SciaRegs.SCIFFTX.bit.TXFFST != 0)
{

}
SciaRegs.SCITXBUF=a;
}

//
// scia_msg - sci xmit through the array
//
void
scia_msg(char * msg)
{
int i;
i = 0;
while(msg[i] != '\0')
{
scia_xmit(msg[i]);
i++;
}
}

//
// scia_fifo_init - Initialize the SCI FIFO
//
void
scia_fifo_init()
{
SciaRegs.SCIFFTX.all=0xE040;
SciaRegs.SCIFFRX.all=0x2044;
SciaRegs.SCIFFCT.all=0x0;
}

// ePWM Subroutines & ISRs
//
// epwm1_isr -
//
__interrupt void
epwm1_isr(void)
{
//
// Update the CMPA and CMPB values
//
//update_compare(&epwm1_info); Turned off by Armani 3/24


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

//
// epwm2_isr -
//
__interrupt void
epwm2_isr(void)
{
//
// Update the CMPA and CMPB values
//
// update_compare(&epwm2_info); Turned off by Armani 3/24


//
// Clear INT flag for this timer
//
EPwm2Regs.ETCLR.bit.INT = 1;

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

//
// epwm3_isr -
//
__interrupt void
epwm3_isr(void)
{
//
// Update the CMPA and CMPB values
//
//update_compare(&epwm3_info); Turned off by Armani 3/24

//
// Clear INT flag for this timer
//
EPwm3Regs.ETCLR.bit.INT = 1;

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

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

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

//
// Setup counter mode
//
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT -- > TBCLK = SYSCLKOUT = 60 MHz
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_3RD; // Generate INT on 3rd event

//
// Information this example uses to keep track of the direction the
// CMPA/CMPB values are moving, the min and max allowed values and
// a pointer to the correct ePWM registers
//

//
// Start by increasing CMPA & decreasing CMPB
//
epwm1_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm1_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN;
epwm1_info.EPwmTimerIntCount = 0; // Zero the interrupt counter

//
// Set the pointer to the ePWM module
//
epwm1_info.EPwmRegHandle = &EPwm1Regs;

//
// Setup min/max CMPA/CMPB values
//
epwm1_info.EPwmMaxCMPA = EPWM1_MAX_CMPA;
epwm1_info.EPwmMinCMPA = EPWM1_MIN_CMPA;
epwm1_info.EPwmMaxCMPB = EPWM1_MAX_CMPB;
epwm1_info.EPwmMinCMPB = EPWM1_MIN_CMPB;
}

//
// InitEPwm2Example -
//
void
InitEPwm2Example()
{
//
// Setup TBCLK
//
EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD; // Set timer period 801 TBCLKs
EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0 -
EPwm2Regs.TBCTR = 0x0000; // Clear counter

//
// Set Compare values
//
EPwm2Regs.CMPA.half.CMPA = EPWM2_MIN_CMPA; // Set compare A value
EPwm2Regs.CMPB = EPWM2_MIN_CMPB; // Set Compare B value

//
// Setup counter mode
//
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading - enable = TB_ENABLE
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;

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

//
// Set actions
//
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM2A on event A, up count
EPwm2Regs.AQCTLA.bit.CBD = AQ_CLEAR; // Clear PWM2A on event B, down count

EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Clear PWM2B on zero
EPwm2Regs.AQCTLB.bit.PRD = AQ_SET ; // Set PWM2B on period

//
// Interrupt where we will change the Compare Values
//
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

//
// Information this example uses to keep track of the direction the
// CMPA/CMPB values are moving, the min and max allowed values and
// a pointer to the correct ePWM registers
//

//
// Start by increasing CMPA & increasing CMPB
//
epwm2_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm2_info.EPwm_CMPB_Direction = EPWM_CMP_UP;

epwm2_info.EPwmTimerIntCount = 0; // Zero the interrupt counter

//
// Set the pointer to the ePWM module
//
epwm2_info.EPwmRegHandle = &EPwm2Regs;

//
// Setup min/max CMPA/CMPB values
//
epwm2_info.EPwmMaxCMPA = EPWM2_MAX_CMPA;
epwm2_info.EPwmMinCMPA = EPWM2_MIN_CMPA;
epwm2_info.EPwmMaxCMPB = EPWM2_MAX_CMPB;
epwm2_info.EPwmMinCMPB = EPWM2_MIN_CMPB;
}

//
// InitEPwm3Example -
//
void
InitEPwm3Example(void)
{
//
// Setup TBCLK
//
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/down
EPwm3Regs.TBPRD = EPWM3_TIMER_TBPRD; // Set timer period
EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm3Regs.TBPHS.half.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;

//
// Setup shadow register load on ZERO
//
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;

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

//
// Set Actions
//
EPwm3Regs.AQCTLA.bit.PRD = AQ_SET; // Set PWM3A on period
EPwm3Regs.AQCTLA.bit.CBD = AQ_CLEAR; // Clear PWM3A on event B, down count

EPwm3Regs.AQCTLB.bit.PRD = AQ_CLEAR; // Clear PWM3A on period
EPwm3Regs.AQCTLB.bit.CAU = AQ_SET; // Set PWM3A on event A, up count

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

//
// Information this example uses to keep track of the direction the
// CMPA/CMPB values are moving, the min and max allowed values and
// a pointer to the correct ePWM registers
//

//
// Start by increasing CMPA & decreasing CMPB
//
epwm3_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm3_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN;

epwm3_info.EPwmTimerIntCount = 0; // Zero the interrupt counter

//
// Set the pointer to the ePWM module
//
epwm3_info.EPwmRegHandle = &EPwm3Regs;

//
// Setup min/max CMPA/CMPB values
//
epwm3_info.EPwmMaxCMPA = EPWM3_MAX_CMPA;
epwm3_info.EPwmMinCMPA = EPWM3_MIN_CMPA;
epwm3_info.EPwmMaxCMPB = EPWM3_MAX_CMPB;
epwm3_info.EPwmMinCMPB = EPWM3_MIN_CMPB;
}

//
// update_compare -
//
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 we were increasing CMPA, check to see if we reached the max value
// If not, increase CMPA else, change directions and decrease CMPA
//
if(epwm_info->EPwm_CMPA_Direction == EPWM_CMP_UP)
{
if(epwm_info->EPwmRegHandle->CMPA.half.CMPA < epwm_info->EPwmMaxCMPA)
{
epwm_info->EPwmRegHandle->CMPA.half.CMPA++;
}
else
{
epwm_info->EPwm_CMPA_Direction = EPWM_CMP_DOWN;
epwm_info->EPwmRegHandle->CMPA.half.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.half.CMPA == epwm_info->EPwmMinCMPA)
{
epwm_info->EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm_info->EPwmRegHandle->CMPA.half.CMPA++;
}
else
{
epwm_info->EPwmRegHandle->CMPA.half.CMPA--;
}
}

//
// If we were increasing CMPB, check to see if we reached the max value
// If not, increase CMPB else, change directions and decrease CMPB
//
if(epwm_info->EPwm_CMPB_Direction == EPWM_CMP_UP)
{
if(epwm_info->EPwmRegHandle->CMPB < epwm_info->EPwmMaxCMPB)
{
epwm_info->EPwmRegHandle->CMPB++;
}
else
{
epwm_info->EPwm_CMPB_Direction = EPWM_CMP_DOWN;
epwm_info->EPwmRegHandle->CMPB--;
}
}

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

else
{
epwm_info->EPwmTimerIntCount++;
}

return;
}

// End of File
//