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.

F28027 ADC


// This program requires the f2802x header files.
//
// Make sure the CPU clock speed is properly defined in
// f2802x_Examples.h before compiling this example.
// Description:
//
// This example sets up the PLL in x12/2 mode.
//
// For 60 MHz devices (default)
// (assuming a 10Mhz input clock).
//
// Interrupts are enabled and the ePWM1 is set up to generate a periodic
// ADC SOC interrupt - ADCINT1. One channel is converted - ADCINA5, which is
// internally connected to the temperature sensor.
//
// Watch Variables:
//
// TempSensorVoltage[10] Last 10 ADCRESULT0 values
// ConversionCount Current result number 0-9
// LoopCount Idle loop counter
//
//
//###########################################################################
// $TI Release: F2802x Support Library v230 $
// $Release Date: Fri May 8 07:43:05 CDT 2015 $
// $Copyright: Copyright (C) 2008-2015 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

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

// Prototype statements for functions found within this file.
__interrupt void adc_isr(void);

// Global variables used in this example:
uint16_t LoopCount;
uint16_t ConversionCount;
uint16_t TempSensorVoltage[10];

void main()
{
// 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

// 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 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 register
PieVectTable.ADCINT1 = &adc_isr;
EDIS; // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize the ADC:
// This function is found in f2802x_Adc.c
InitAdc(); // For this example, init the ADC
AdcOffsetSelfCal();

// Step 5. Configure ADC to sample the temperature sensor on ADCIN5:
// The output of Piccolo temperature sensor can be internally connected to the ADC through ADCINA5
// via the TEMPCONV bit in the ADCCTL1 register. When this bit is set, any voltage applied to the external
// ADCIN5 pin is ignored.
EALLOW;
AdcRegs.ADCCTL1.bit.TEMPCONV = 1; //Connect internal temp sensor to channel ADCINA5.
EDIS;

// Step 6. Continue configuring ADC to sample the temperature sensor on ADCIN5:
// Since the temperature sensor is connected to ADCIN5, configure the ADC to sample channel ADCIN5
// as well as the ADC SOC trigger and ADCINTs preferred. This example uses EPWM1A to trigger the ADC
// to start a conversion and trips ADCINT1 at the end of the conversion.

//Note: The temperature sensor will be double sampled to apply the workaround for rev0 silicon errata for the ADC 1st sample issue
EALLOW;
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINT1 trips after AdcResults latch
AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
AdcRegs.INTSEL1N2.bit.INT1SEL = 1; //setup EOC1 to trigger ADCINT1 to fire
AdcRegs.ADCSOC0CTL.bit.CHSEL = 5; //set SOC0 channel select to ADCINA5 (which is internally connected to the temperature sensor)
AdcRegs.ADCSOC1CTL.bit.CHSEL = 5; //set SOC1 channel select to ADCINA5 (which is internally connected to the temperature sensor) errata workaround
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //set SOC0 start trigger on EPWM1A
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; //set SOC1 start trigger on EPWM1A errata workaround
AdcRegs.ADCSOC0CTL.bit.ACQPS = 36; //set SOC0 S/H Window to 37 ADC Clock Cycles, (36 ACQPS plus 1)
AdcRegs.ADCSOC1CTL.bit.ACQPS = 36; //set SOC1 S/H Window to 37 ADC Clock Cycles, (36 ACQPS plus 1) errata workaround
EDIS;

// Step 7. User specific code, enable interrupts:
// Enable ADCINT1 in PIE
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

LoopCount = 0;
ConversionCount = 0;

// Assumes ePWM1 clock is already enabled in InitSysCtrl();
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC from from CPMA on upcount
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm1Regs.CMPA.half.CMPA = 0x0080; // Set compare A value
EPwm1Regs.TBPRD = 0xFFFF; // Set period for ePWM1
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // count up and start

// Wait for ADC interrupt
for(;;)
{
LoopCount++;
}
}

__interrupt void adc_isr(void)
{
TempSensorVoltage[ConversionCount] = AdcResult.ADCRESULT1; //discard ADCRESULT0 as part of the workaround to the 1st sample errata for rev0

// If 20 conversions have been logged, start over
if(ConversionCount == 9)
{
ConversionCount = 0;
}
else
{
ConversionCount++;
}

AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE

return;
}

  • //###########################################################################
    //
    // FILE: Example_2802xCpuTimer.c
    //
    // TITLE: f2802x Device Getting Started Program.
    //
    // ASSUMPTIONS:
    //
    // This program requires the f2802x header files.
    //
    // Other then boot mode configuration, no other hardware configuration
    // is required.
    //
    //
    // 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 example configures CPU Timer0, 1, & 2 and increments
    // a counter each time the timer asserts an interrupt.
    //
    // Watch Variables:
    // CpuTimer0.InterruptCount
    // CpuTimer1.InterruptCount
    // CpuTimer2.InterruptCount
    //
    //###########################################################################
    // $TI Release: F2802x Support Library v230 $
    // $Release Date: Fri May 8 07:43:05 CDT 2015 $
    // $Copyright: Copyright (C) 2008-2015 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

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

    // Prototype statements for functions found within this file.
    __interrupt void cpu_timer0_isr(void);
    __interrupt void cpu_timer1_isr(void);
    __interrupt void cpu_timer2_isr(void);

    void main(void)
    {
    // 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

    // 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 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.TINT0 = &cpu_timer0_isr;
    PieVectTable.TINT1 = &cpu_timer1_isr;
    PieVectTable.TINT2 = &cpu_timer2_isr;
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Step 4. Initialize the Device Peripheral. This function can be
    // found in f2802x_CpuTimers.c
    InitCpuTimers(); // For this example, only initialize the Cpu Timers

    #if (CPU_FRQ_60MHZ)
    // Configure CPU-Timer 0, 1, and 2 to interrupt every second:
    // 60MHz CPU Freq, 1 second Period (in uSeconds)

    ConfigCpuTimer(&CpuTimer0, 60, 1000000);
    ConfigCpuTimer(&CpuTimer1, 60, 1000000);
    ConfigCpuTimer(&CpuTimer2, 60, 1000000);
    #endif
    #if (CPU_FRQ_50MHZ)
    // Configure CPU-Timer 0, 1, and 2 to interrupt every second:
    // 50MHz CPU Freq, 1 second Period (in uSeconds)

    ConfigCpuTimer(&CpuTimer0, 50, 1000000);
    ConfigCpuTimer(&CpuTimer1, 50, 1000000);
    ConfigCpuTimer(&CpuTimer2, 50, 1000000);
    #endif
    #if (CPU_FRQ_40MHZ)
    // Configure CPU-Timer 0, 1, and 2 to interrupt every second:
    // 40MHz CPU Freq, 1 second Period (in uSeconds)

    ConfigCpuTimer(&CpuTimer0, 40, 1000000);
    ConfigCpuTimer(&CpuTimer1, 40, 1000000);
    ConfigCpuTimer(&CpuTimer2, 40, 1000000);
    #endif
    // To ensure precise timing, use write-only instructions to write to the entire
    // register. Therefore, if any of the configuration bits are changed in
    // ConfigCpuTimer and InitCpuTimers (in f2802x_CpuTimers.h), the
    // below settings must also be updated.

    CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
    CpuTimer1Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
    CpuTimer2Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0

    // Step 5. User specific code, enable interrupts:

    // Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
    // which is connected to CPU-Timer 1, and CPU int 14, which is connected
    // to CPU-Timer 2:
    IER |= M_INT1;
    IER |= M_INT13;
    IER |= M_INT14;

    // Enable TINT0 in the PIE: Group 1 interrupt 7
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

    // Enable global Interrupts and higher priority real-time debug events:
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM

    // Step 6. IDLE loop. Just sit and loop forever (optional):
    for(;;);
    }

    __interrupt void cpu_timer0_isr(void)
    {
    CpuTimer0.InterruptCount++;

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

    __interrupt void cpu_timer1_isr(void)
    {
    CpuTimer1.InterruptCount++;
    // The CPU acknowledges the interrupt.
    EDIS;
    }

    __interrupt void cpu_timer2_isr(void)
    { EALLOW;
    CpuTimer2.InterruptCount++;
    // The CPU acknowledges the interrupt.
    EDIS;
    }

    //===========================================================================
    // No more.
    //===========================================================================
  • 不好意思,我只是想借助网页翻译,就像您说的应该先把程序看懂
  • //###########################################################################
    //
    // FILE: Example_2802xEPwmUpDownAQ.c
    //
    // TITLE: Action Qualifier Module - Using up/down count
    //
    // ASSUMPTIONS:
    //
    // This program requires the f2802x header files.
    //
    // Monitor ePWM1-ePWM3 pins on an oscilloscope as described
    // below.
    //
    // EPWM1A is on GPIO0
    // EPWM1B is on GPIO1
    //
    // EPWM2A is on GPIO2
    // EPWM2B is on GPIO3
    //
    // EPWM3A is on GPIO4
    // EPWM3B is on GPIO5
    //
    // 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 example configures ePWM1, ePWM2, ePWM3 to produce an
    // waveform with independent modulation on EPWMxA and
    // EPWMxB.
    //
    // The compare values CMPA and CMPB are modified within the ePWM's ISR
    //
    // The TB counter is in up/down count mode for this example.
    //
    // View the EPWM1A/B, EPWM2A/B and EPWM3A/B waveforms
    // via an oscilloscope
    //
    //
    //###########################################################################
    // $TI Release: F2802x Support Library v230 $
    // $Release Date: Fri May 8 07:43:05 CDT 2015 $
    // $Copyright: Copyright (C) 2008-2015 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

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

    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;

    // 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 variables used in this example
    EPWM_INFO epwm1_info;
    EPWM_INFO epwm2_info;
    EPWM_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 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

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

    void main(void)
    {
    // 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 this case just init GPIO pins for ePWM1, ePWM2, ePWM3
    // These functions are in the f2802x_EPwm.c file
    InitEPwm1Gpio();
    InitEPwm2Gpio();
    InitEPwm3Gpio();

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

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

    // 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 5. User specific code, enable 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 realtime interrupt DBGM

    // Step 6. IDLE loop. Just sit and loop forever (optional):
    for(;;)
    {
    __asm(" NOP");
    }
    }

    __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.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
    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
    epwm1_info.EPwm_CMPA_Direction = EPWM_CMP_UP; // Start by increasing CMPA &
    epwm1_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN; // decreasing CMPB
    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 values
    epwm1_info.EPwmMinCMPA = EPWM1_MIN_CMPA;
    epwm1_info.EPwmMaxCMPB = EPWM1_MAX_CMPB;
    epwm1_info.EPwmMinCMPB = EPWM1_MIN_CMPB;
    }

    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
    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
    epwm2_info.EPwm_CMPA_Direction = EPWM_CMP_UP; // Start by increasing CMPA &
    epwm2_info.EPwm_CMPB_Direction = EPWM_CMP_UP; // increasing CMPB
    epwm2_info.EPwmTimerIntCount = 0; // Zero the interrupt counter
    epwm2_info.EPwmRegHandle = &EPwm2Regs; // Set the pointer to the ePWM module
    epwm2_info.EPwmMaxCMPA = EPWM2_MAX_CMPA; // Setup min/max CMPA/CMPB values
    epwm2_info.EPwmMinCMPA = EPWM2_MIN_CMPA;
    epwm2_info.EPwmMaxCMPB = EPWM2_MAX_CMPB;
    epwm2_info.EPwmMinCMPB = EPWM2_MIN_CMPB;
    }

    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
    epwm3_info.EPwm_CMPA_Direction = EPWM_CMP_UP; // Start by increasing CMPA &
    epwm3_info.EPwm_CMPB_Direction = EPWM_CMP_DOWN; // decreasing CMPB
    epwm3_info.EPwmTimerIntCount = 0; // Zero the interrupt counter
    epwm3_info.EPwmRegHandle = &EPwm3Regs; // Set the pointer to the ePWM module
    epwm3_info.EPwmMaxCMPA = EPWM3_MAX_CMPA; // Setup min/max CMPA/CMPB values
    epwm3_info.EPwmMinCMPA = EPWM3_MIN_CMPA;
    epwm3_info.EPwmMaxCMPB = EPWM3_MAX_CMPB;
    epwm3_info.EPwmMinCMPB = EPWM3_MIN_CMPB;
    }

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



    //===========================================================================
    // No more.
    //===========================================================================
  • //###########################################################################
    //
    // 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 v230 $
    // $Release Date: Fri May 8 07:43:05 CDT 2015 $
    // $Copyright: Copyright (C) 2008-2015 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

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

    // Prototype statements for functions found within this file.
    void scia_echoback_init(void);
    void scia_fifo_init(void);
    void scia_xmit(int a);
    void scia_msg(char *msg);

    // Global counts used in this example
    uint16_t LoopCount;
    uint16_t ErrorCount;

    void main(void)
    {
    Uint16 ReceivedChar;
    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 this example, only init the pins for the SCI-A port.
    // This function is found in the f2802x_Sci.c file.
    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();

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

    // Step 5. User specific code:

    LoopCount = 0;
    ErrorCount = 0;

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

    msg = "\r\n\n\nHello World!\0";
    scia_msg(msg);

    msg = "\r\nYou will enter a character, and the DSP will echo it back! \n\0";
    scia_msg(msg);

    for(;;)
    {
    msg = "\r\nEnter a character: \0";
    scia_msg(msg);

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

    // Get character
    ReceivedChar = SciaRegs.SCIRXBUF.all;

    // Echo character back
    msg = " You sent: \0";
    scia_msg(msg);
    scia_xmit(ReceivedChar);

    LoopCount++;
    }
    }

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

    SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
    // No parity,8 char bits,
    // async mode, idle-line protocol
    SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
    // Disable RX ERR, SLEEP, TXWAKE
    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
    }

    // Transmit a character from the SCI
    void scia_xmit(int a)
    {
    while (SciaRegs.SCIFFTX.bit.TXFFST != 0) {}
    SciaRegs.SCITXBUF=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()
    {
    SciaRegs.SCIFFTX.all=0xE040;
    SciaRegs.SCIFFRX.all=0x2044;
    SciaRegs.SCIFFCT.all=0x0;
    }

    //===========================================================================
    // No more.
    //===========================================================================
  • //###########################################################################
    //
    // FILE: Example_2802xI2c_eeprom.c
    //
    // TITLE: f2802x I2C EEPROM Example
    //
    // ASSUMPTIONS:
    //
    // This program requires the f2802x header files.
    //
    // This program requires an external I2C EEPROM connected to
    // the I2C bus at address 0x50.
    //
    // 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 program will write 1-14 words to EEPROM and read them back.
    // The data written and the EEPROM address written to are contained
    // in the message structure, I2cMsgOut1. The data read back will be
    // contained in the message structure I2cMsgIn1.
    //
    // This program will work with the on-board I2C EEPROM supplied on
    // the F2802x eZdsp.
    //
    //
    //###########################################################################
    // $TI Release: F2802x Support Library v230 $
    // $Release Date: Fri May 8 07:43:05 CDT 2015 $
    // $Copyright: Copyright (C) 2008-2015 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

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

    // Note: I2C Macros used in this example can be found in the
    // f2802x_I2C_defines.h file

    // Prototype statements for functions found within this file.
    void I2CA_Init(void);
    uint16_t I2CA_WriteData(struct I2CMSG *msg);
    uint16_t I2CA_ReadData(struct I2CMSG *msg);
    __interrupt void i2c_int1a_isr(void);
    void pass(void);
    void fail(void);

    #define I2C_SLAVE_ADDR 0x50
    #define I2C_NUMBYTES 2
    #define I2C_EEPROM_HIGH_ADDR 0x00
    #define I2C_EEPROM_LOW_ADDR 0x30

    // Global variables
    // Two bytes will be used for the outgoing address,
    // thus only setup 14 bytes maximum
    struct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP,
    I2C_SLAVE_ADDR,
    I2C_NUMBYTES,
    I2C_EEPROM_HIGH_ADDR,
    I2C_EEPROM_LOW_ADDR,
    0x12, // Msg Byte 1
    0x34}; // Msg Byte 2


    struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP,
    I2C_SLAVE_ADDR,
    I2C_NUMBYTES,
    I2C_EEPROM_HIGH_ADDR,
    I2C_EEPROM_LOW_ADDR};

    struct I2CMSG *CurrentMsgPtr; // Used in interrupts
    uint16_t PassCount;
    uint16_t FailCount;

    void main(void)
    {
    uint16_t Error;
    uint16_t i;

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

    CurrentMsgPtr = &I2cMsgOut1;

    // 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();
    // Setup only the GP I/O only for I2C functionality
    InitI2CGpio();

    // 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.I2CINT1A = &i2c_int1a_isr;
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Step 4. Initialize all the Device Peripherals:
    I2CA_Init(); // I2C-A only

    // Step 5. User specific code

    // Clear Counters
    PassCount = 0;
    FailCount = 0;

    // Clear incoming message buffer
    for (i = 0; i < (I2C_MAX_BUFFER_SIZE - 2); i++)
    {
    I2cMsgIn1.MsgBuffer[i] = 0x0000;
    }

    // Enable interrupts required for this example

    // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

    // Enable CPU INT8 which is connected to PIE group 8
    IER |= M_INT8;
    EINT;

    // Application loop
    for(;;)
    {
    //////////////////////////////////
    // Write data to EEPROM section //
    //////////////////////////////////

    // Check the outgoing message to see if it should be sent.
    // In this example it is initialized to send with a stop bit.
    if(I2cMsgOut1.MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP)
    {
    Error = I2CA_WriteData(&I2cMsgOut1);
    // If communication is correctly initiated, set msg status to busy
    // and update CurrentMsgPtr for the interrupt service routine.
    // Otherwise, do nothing and try again next loop. Once message is
    // initiated, the I2C interrupts will handle the rest. Search for
    // ICINTR1A_ISR in the i2c_eeprom_isr.c file.
    if (Error == I2C_SUCCESS)
    {
    CurrentMsgPtr = &I2cMsgOut1;
    I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY;
    }
    } // end of write section

    ///////////////////////////////////
    // Read data from EEPROM section //
    ///////////////////////////////////

    // Check outgoing message status. Bypass read section if status is
    // not inactive.
    if (I2cMsgOut1.MsgStatus == I2C_MSGSTAT_INACTIVE)
    {
    // Check incoming message status.
    if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)
    {
    // EEPROM address setup portion
    while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)
    {
    // Maybe setup an attempt counter to break an infinite while
    // loop. The EEPROM will send back a NACK while it is performing
    // a write operation. Even though the write communique is
    // complete at this point, the EEPROM could still be busy
    // programming the data. Therefore, multiple attempts are
    // necessary.
    }
    // Update current message pointer and message status
    CurrentMsgPtr = &I2cMsgIn1;
    I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY;
    }

    // Once message has progressed past setting up the internal address
    // of the EEPROM, send a restart to read the data bytes from the
    // EEPROM. Complete the communique with a stop bit. MsgStatus is
    // updated in the interrupt service routine.
    else if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_RESTART)
    {
    // Read data portion
    while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)
    {
    // Maybe setup an attempt counter to break an infinite while
    // loop.
    }
    // Update current message pointer and message status
    CurrentMsgPtr = &I2cMsgIn1;
    I2cMsgIn1.MsgStatus = I2C_MSGSTAT_READ_BUSY;
    }
    } // end of read section
    } // end of for(;;)
    } // end of main

    void I2CA_Init(void)
    {
    // Initialize I2C
    I2caRegs.I2CSAR = 0x0050; // Slave address - EEPROM control code

    // I2CCLK = SYSCLK/(I2CPSC+1)
    #if (CPU_FRQ_40MHZ||CPU_FRQ_50MHZ)
    I2caRegs.I2CPSC.all = 4; // Prescaler - need 7-12 Mhz on module clk
    #endif

    #if (CPU_FRQ_60MHZ)
    I2caRegs.I2CPSC.all = 6; // Prescaler - need 7-12 Mhz on module clk
    #endif
    I2caRegs.I2CCLKL = 10; // NOTE: must be non zero
    I2caRegs.I2CCLKH = 5; // NOTE: must be non zero
    I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts

    I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset
    // Stop I2C when suspended

    I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO
    I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT,

    return;
    }

    uint16_t I2CA_WriteData(struct I2CMSG *msg)
    {
    uint16_t i;

    // Wait until the STP bit is cleared from any previous master communication.
    // Clearing of this bit by the module is delayed until after the SCD bit is
    // set. If this bit is not checked prior to initiating a new message, the
    // I2C could get confused.
    if (I2caRegs.I2CMDR.bit.STP == 1)
    {
    return I2C_STP_NOT_READY_ERROR;
    }

    // Setup slave address
    I2caRegs.I2CSAR = msg->SlaveAddress;

    // Check if bus busy
    if (I2caRegs.I2CSTR.bit.BB == 1)
    {
    return I2C_BUS_BUSY_ERROR;
    }

    // Setup number of bytes to send
    // MsgBuffer + Address
    I2caRegs.I2CCNT = msg->NumOfBytes+2;

    // Setup data to send
    I2caRegs.I2CDXR = msg->MemoryHighAddr;
    I2caRegs.I2CDXR = msg->MemoryLowAddr;

    for (i=0; i<msg->NumOfBytes; i++)
    {
    I2caRegs.I2CDXR = *(msg->MsgBuffer+i);
    }

    // Send start as master transmitter
    I2caRegs.I2CMDR.all = 0x6E20;

    return I2C_SUCCESS;
    }

    uint16_t I2CA_ReadData(struct I2CMSG *msg)
    {
    // Wait until the STP bit is cleared from any previous master communication.
    // Clearing of this bit by the module is delayed until after the SCD bit is
    // set. If this bit is not checked prior to initiating a new message, the
    // I2C could get confused.
    if (I2caRegs.I2CMDR.bit.STP == 1)
    {
    return I2C_STP_NOT_READY_ERROR;
    }

    I2caRegs.I2CSAR = msg->SlaveAddress;

    if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)
    {
    // Check if bus busy
    if (I2caRegs.I2CSTR.bit.BB == 1)
    {
    return I2C_BUS_BUSY_ERROR;
    }
    I2caRegs.I2CCNT = 2;
    I2caRegs.I2CDXR = msg->MemoryHighAddr;
    I2caRegs.I2CDXR = msg->MemoryLowAddr;
    I2caRegs.I2CMDR.all = 0x2620; // Send data to setup EEPROM address
    }
    else if(msg->MsgStatus == I2C_MSGSTAT_RESTART)
    {
    I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect
    I2caRegs.I2CMDR.all = 0x2C20; // Send restart as master receiver
    }

    return I2C_SUCCESS;
    }

    __interrupt void i2c_int1a_isr(void) // I2C-A
    {
    uint16_t IntSource, i;

    // Read interrupt source
    IntSource = I2caRegs.I2CISRC.all;

    // Interrupt source = stop condition detected
    if(IntSource == I2C_SCD_ISRC)
    {
    // If completed message was writing data, reset msg to inactive state
    if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY)
    {
    CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;
    }
    else
    {
    // If a message receives a NACK during the address setup portion of the
    // EEPROM read, the code further below included in the register access ready
    // interrupt source code will generate a stop condition. After the stop
    // condition is received (here), set the message status to try again.
    // User may want to limit the number of retries before generating an error.
    if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
    {
    CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
    }
    // If completed message was reading EEPROM data, reset msg to inactive state
    // and read data from FIFO.
    else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY)
    {
    CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;
    for(i=0; i < I2C_NUMBYTES; i++)
    {
    CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR;
    }
    {
    // Check received data
    for(i=0; i < I2C_NUMBYTES; i++)
    {
    if(I2cMsgIn1.MsgBuffer[i] == I2cMsgOut1.MsgBuffer[i])
    {
    PassCount++;
    }
    else
    {
    FailCount++;
    }
    }
    if(PassCount == I2C_NUMBYTES)
    {
    pass();
    }
    else
    {
    fail();
    }
    }
    }
    }
    } // end of stop condition detected

    // Interrupt source = Register Access Ready
    // This interrupt is used to determine when the EEPROM address setup portion of the
    // read data communication is complete. Since no stop bit is commanded, this flag
    // tells us when the message has been sent instead of the SCD flag. If a NACK is
    // received, clear the NACK bit and command a stop. Otherwise, move on to the read
    // data portion of the communication.
    else if(IntSource == I2C_ARDY_ISRC)
    {
    if(I2caRegs.I2CSTR.bit.NACK == 1)
    {
    I2caRegs.I2CMDR.bit.STP = 1;
    I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
    }
    else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
    {
    CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;
    }
    } // end of register access ready

    else
    {
    // Generate some error due to invalid interrupt source
    __asm(" ESTOP0");
    }

    // Enable future I2C (PIE Group 8) interrupts
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
    }

    void pass()
    {
    __asm(" ESTOP0");
    for(;;);
    }

    void fail()
    {
    __asm(" ESTOP0");
    for(;;);
    }

    //===========================================================================
    // No more.
    //===========================================================================