You are on page 1of 9

// TI File $Revision: /main/2 $

// Checkin $Date: July 30, 2009 18:44:13 $


//###########################################################################
//
// FILE: Example_2833xAdc.c
//
// TITLE: DSP2833x ADC Example Program.
//
// ASSUMPTIONS:
//
// This program requires the DSP2833x header files.
//
// Make sure the CPU clock speed is properly defined in
// DSP2833x_Examples.h before compiling this example.
//
// Connect signals to be converted to A2 and A3.
//
//
As supplied, this project is configured for "boot to SARAM"
//
operation. The 2833x 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:
//
//
GPIO87 GPIO86
GPIO85 GPIO84
//
XA15
XA14
XA13
XA12
//
PU
PU
PU
PU
//
==========================================
//
1
1
1
1
Jump to Flash
//
1
1
1
0
SCI-A boot
//
1
1
0
1
SPI-A boot
//
1
1
0
0
I2C-A boot
//
1
0
1
1
eCAN-A boot
//
1
0
1
0
McBSP-A boot
//
1
0
0
1
Jump to XINTF x16
//
1
0
0
0
Jump to XINTF x32
//
0
1
1
1
Jump to OTP
//
0
1
1
0
Parallel GPIO I/O boot
//
0
1
0
1
Parallel XINTF boot
//
0
1
0
0
Jump to SARAM
<- "boot to
SARAM"
//
0
0
1
1
Branch to check boot mode
//
0
0
1
0
Boot to flash, bypass ADC cal
//
0
0
0
1
Boot to SARAM, bypass ADC cal
//
0
0
0
0
Boot to SCI-A, bypass ADC cal
//
Boot_Table_End$
//
// DESCRIPTION:
//
// This example sets up the PLL in x10/2 mode.
//
// For 150 MHz devices (default)
// divides SYSCLKOUT by six to reach a 25.0Mhz HSPCLK
// (assuming a 30Mhz XCLKIN).
//
// For 100 MHz devices:
// divides SYSCLKOUT by four to reach a 25.0Mhz HSPCLK
// (assuming a 20Mhz XCLKIN).
//
// Interrupts are enabled and the ePWM1 is setup to generate a periodic

// ADC SOC on SEQ1. Two channels are converted, ADCINA3 and ADCINA2.
//
// Watch Variables:
//
//
Voltage1[10]
Last 10 ADCRESULT0 values
//
Voltage2[10]
Last 10 ADCRESULT1 values
//
ConversionCount Current result number 0-9
//
LoopCount
Idle loop counter
//
//
//###########################################################################
//
// Original Author: D.F.
//
// $TI Release: DSP2833x/DSP2823x C/C++ Header Files V1.31 $
// $Release Date: August 4, 2009 $
//###########################################################################
#include "DSP28x_Project.h"

// Device Headerfile and Examples Include File

// Prototype statements for functions found within this file.


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;

// Prototype statements for functions found within this file.


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*);
// Global
EPWM_INFO
EPWM_INFO
EPWM_INFO

variables used in this example


epwm1_info;
epwm2_info;
epwm3_info;

// Configure the period for each timer


#define EPWM1_TIMER_TBPRD 2000 // Period register
#define EPWM1_MAX_CMPA
1950
#define EPWM1_MIN_CMPA
50
#define EPWM1_MAX_CMPB
1950
#define EPWM1_MIN_CMPB
50
#define EPWM2_TIMER_TBPRD 2000 // Period register
#define EPWM2_MAX_CMPA
1950
#define EPWM2_MIN_CMPA
50

#define EPWM2_MAX_CMPB
#define EPWM2_MIN_CMPB
#define
#define
#define
#define
#define

1950
50

EPWM3_TIMER_TBPRD 2000 // Period register


EPWM3_MAX_CMPA
950
EPWM3_MIN_CMPA
50
EPWM3_MAX_CMPB
1950
EPWM3_MIN_CMPB
1050

// To keep track of which way the compare value is moving


#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
interrupt void adc_isr(void);
// Global variables used in this example:
Uint16 LoopCount;
Uint16 ConversionCount;
Uint16 Voltage1[10];
Uint16 Voltage2[10];
main()
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
InitSysCtrl();
InitEPwm1Gpio();
InitEPwm2Gpio();
InitEPwm3Gpio();

EALLOW;
#if (CPU_FRQ_150MHZ)
// Default - 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)
25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
#define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)
25.0 MHz
#endif
EDIS;
//
//
//
//

Step 2. Initialize GPIO:


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

// 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 DSP2833x_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 DSP2833x_DefaultIsr.c.
This function is found in DSP2833x_PieVect.c.
InitPieVectTable();

// Interrupts that are


// ISR functions found
EALLOW; // This is
PieVectTable.ADCINT
EDIS;
// This is

used in this example are re-mapped to


within this file.
needed to write to EALLOW protected register
= &adc_isr;
needed to disable write to EALLOW protected registers

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
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
InitEPwm1Example();
InitEPwm2Example();
InitEPwm3Example();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// 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;
// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
InitAdc(); // For this example, init the ADC
// Step 5. User specific code, enable interrupts:
// Enable ADCINT in PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
IER |= M_INT1; // Enable CPU Interrupt 1
EINT;
// Enable Global interrupt INTM
ERTM;
// Enable Global realtime interrupt DBGM

LoopCount = 0;
ConversionCount = 0;
// Configure ADC
AdcRegs.ADCMAXCONV.all = 0x0001;
//
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; //
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; //
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;//
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; //
// Assumes ePWM1 clock is already enabled
EPwm1Regs.ETSEL.bit.SOCAEN = 1;
EPwm1Regs.ETSEL.bit.SOCASEL = 4;
t
EPwm1Regs.ETPS.bit.SOCAPRD = 1;
EPwm1Regs.CMPA.half.CMPA = 0x0080;
EPwm1Regs.TBPRD = 0xFFFF;
EPwm1Regs.TBCTL.bit.CTRMODE = 0;

Setup 2 conv's on SEQ1


Setup ADCINA3 as 1st SEQ1 conv.
Setup ADCINA2 as 2nd SEQ1 conv.
Enable SOCA from ePWM to start SEQ1
Enable SEQ1 interrupt (every EOS)

in InitSysCtrl();
// Enable SOC on A group
// Select SOC from from CPMA on upcoun
// Generate pulse on 1st event
// Set compare A value
// Set period for ePWM1
// count up and start

// Wait for ADC interrupt


for(;;)
{
LoopCount++;

}
}
interrupt void epwm1_isr(void)
{
// Update the CMPA and CMPB values
update_compare(&epwm1_info);
// 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;
}
interrupt void epwm2_isr(void)
{
// Update the CMPA and CMPB values
update_compare(&epwm2_info);
// 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;
}
interrupt void epwm3_isr(void)

{
// Update the CMPA and CMPB values
update_compare(&epwm3_info);
// 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;
}
void InitEPwm1Example()
{
// Setup TBCLK
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm1Regs.TBPHS.half.TBPHS = 0x0000;
EPwm1Regs.TBCTR = 0x0000;
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2;
// Setup shadow register load on
EPwm1Regs.CMPCTL.bit.SHDWAMODE =
EPwm1Regs.CMPCTL.bit.SHDWBMODE =
EPwm1Regs.CMPCTL.bit.LOADAMODE =
EPwm1Regs.CMPCTL.bit.LOADBMODE =

//
//
//
//
//
//

Count up
Set timer period
Disable phase loading
Phase is 0
Clear counter
Clock ratio to SYSCLKOUT

ZERO
CC_SHADOW;
CC_SHADOW;
CC_CTR_ZERO;
CC_CTR_ZERO;

// Set Compare values


EPwm1Regs.CMPA.half.CMPA = EPWM1_MIN_CMPA;
EPwm1Regs.CMPB = EPWM1_MIN_CMPB;

// Set compare A value


// Set Compare B value

// Set actions
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
ount

// Set PWM1A on Zero


// Clear PWM1A on event A, up c

EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;
ount

// Set PWM1B on Zero


// Clear PWM1B on event B, up c

// Interrupt where we will change the Compare


EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm1Regs.ETSEL.bit.INTEN = 1;
EPwm1Regs.ETPS.bit.INTPRD = ET_3RD;

Values
// Select INT on Zero event
// Enable INT
// 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
epwm1_info.EPwm_CMPA_Direction = EPWM_CMP_UP; // Start by increasing CMPA & C
MPB
epwm1_info.EPwm_CMPB_Direction = EPWM_CMP_UP;
epwm1_info.EPwmTimerIntCount = 0;
// Zero the interrupt counter
epwm1_info.EPwmRegHandle = &EPwm1Regs;
// Set the pointer to the ePWM
module
epwm1_info.EPwmMaxCMPA = EPWM1_MAX_CMPA;
// Setup min/max CMPA/CMPB valu
es

epwm1_info.EPwmMinCMPA = EPWM1_MIN_CMPA;
epwm1_info.EPwmMaxCMPB = EPWM1_MAX_CMPB;
epwm1_info.EPwmMinCMPB = EPWM1_MIN_CMPB;
}
void InitEPwm2Example()
{
// Setup TBCLK
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD;
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm2Regs.TBPHS.half.TBPHS = 0x0000;
EPwm2Regs.TBCTR = 0x0000;
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV2;
// Setup shadow register load on
EPwm2Regs.CMPCTL.bit.SHDWAMODE =
EPwm2Regs.CMPCTL.bit.SHDWBMODE =
EPwm2Regs.CMPCTL.bit.LOADAMODE =
EPwm2Regs.CMPCTL.bit.LOADBMODE =

//
//
//
//
//
//

Count up
Set timer period
Disable phase loading
Phase is 0
Clear counter
Clock ratio to SYSCLKOUT

ZERO
CC_SHADOW;
CC_SHADOW;
CC_CTR_ZERO;
CC_CTR_ZERO;

// Set Compare values


EPwm2Regs.CMPA.half.CMPA = EPWM2_MIN_CMPA;
EPwm2Regs.CMPB = EPWM2_MAX_CMPB;

// Set compare A value


// Set Compare B value

// Set actions
EPwm2Regs.AQCTLA.bit.PRD = AQ_CLEAR;
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;
count

// Clear PWM2A on Period


// Set PWM2A on event A, up

EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR;
EPwm2Regs.AQCTLB.bit.CBU = AQ_SET;
count

// Clear PWM2B on Period


// Set PWM2B on event B, up

// 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
epwm2_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
// Start by increasing CMPA
epwm2_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN; // and decreasing CMPB
epwm2_info.EPwmTimerIntCount = 0;
// Zero the interrupt counte
r
epwm2_info.EPwmRegHandle
WM module
epwm2_info.EPwmMaxCMPA =
alues
epwm2_info.EPwmMinCMPA =
epwm2_info.EPwmMaxCMPB =
epwm2_info.EPwmMinCMPB =
}

= &EPwm2Regs;

// Set the pointer to the eP

EPWM2_MAX_CMPA;

// Setup min/max CMPA/CMPB v

EPWM2_MIN_CMPA;
EPWM2_MAX_CMPB;
EPWM2_MIN_CMPB;

void InitEPwm3Example(void)
{
// Setup TBCLK
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm3Regs.TBPRD = EPWM3_TIMER_TBPRD;
EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm3Regs.TBPHS.half.TBPHS = 0x0000;
EPwm3Regs.TBCTR = 0x0000;
EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadow register load on
EPwm3Regs.CMPCTL.bit.SHDWAMODE =
EPwm3Regs.CMPCTL.bit.SHDWBMODE =
EPwm3Regs.CMPCTL.bit.LOADAMODE =
EPwm3Regs.CMPCTL.bit.LOADBMODE =

//
//
//
//
//
//

Count up
Set timer period
Disable phase loading
Phase is 0
Clear counter
Clock ratio to SYSCLKOUT

ZERO
CC_SHADOW;
CC_SHADOW;
CC_CTR_ZERO;
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.CAU = AQ_SET;
EPwm3Regs.AQCTLA.bit.CBU = AQ_CLEAR;

// Set PWM3A on event B, up count


// Clear PWM3A on event B, up coun

EPwm3Regs.AQCTLB.bit.ZRO = AQ_TOGGLE;

// Toggle EPWM3B on Zero

// Interrupt where we will change the Compare


EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm3Regs.ETSEL.bit.INTEN = 1;
EPwm3Regs.ETPS.bit.INTPRD = ET_3RD;

Values
// Select INT on Zero event
// Enable INT
// Generate INT on 3rd event

// Start by increasing the compare A and decreasing compare B


epwm3_info.EPwm_CMPA_Direction = EPWM_CMP_UP;
epwm3_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN;
// Start the cout at 0
epwm3_info.EPwmTimerIntCount = 0;
epwm3_info.EPwmRegHandle = &EPwm3Regs;
epwm3_info.EPwmMaxCMPA = EPWM3_MAX_CMPA;
epwm3_info.EPwmMinCMPA = EPWM3_MIN_CMPA;
epwm3_info.EPwmMaxCMPB = EPWM3_MAX_CMPB;
epwm3_info.EPwmMinCMPB = EPWM3_MIN_CMPB;
}

interrupt void adc_isr(void)


{
Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;

// If 40 conversions have been logged, start over


if(ConversionCount == 9)

{
ConversionCount = 0;
}
else ConversionCount++;
// Reinitialize for next ADC sequence
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

// Reset SEQ1
// Clear INT SEQ1 bit
// Acknowledge interrupt to PIE

return;
}
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->EPwmMa
xCMPA)
{
epwm_info->EPwmRegHandle->CMPA.half.CMPA++;
}
else
{
epwm_info->EPwm_CMPA_Direction = EPWM_CMP_DOWN;
epwm_info->EPwmRegHandle->CMPA.half.CMPA--;
}
*/
epwm_info->EPwmRegHandle->CMPA.half.CMPA= AdcRegs.ADCRESULT1
>>4;
}
}
else
{
epwm_info->EPwmTimerIntCount++;
}
return;
}