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.

Pulse generation using GPIO and CPU timer interrupt-F28335

Other Parts Discussed in Thread: CONTROLSUITE

HI

I want to generate pulses having variable frequency and duty ratio using GPIO pins and CPU timer interrupts in F28335

I have come up with two ideas:

1. Using GPIO toggle by GPIO DATA/SET/Toggle registers.

I am trying to this,but for that i need to write a logic which should provide option to the user to change the frequency/time period and duty ratio.For now just trying to observe the pulse pattern with GPIO1

I have included math.h file also,but I am not very clear with the declaration procedures for variables, as i am getting error with declaration.

1351.gpio toggle.txt
// TI File $Revision: /main/3 $
// Checkin $Date: June 23, 2010   09:28:07 $
//###########################################################################
//
// FILE:    Example_2833xGpioToggle.c
//
// TITLE:   DSP2833x Device GPIO toggle test program. 
//
// ASSUMPTIONS:
//
//    This program requires the DSP2833x header files.  
//
//    ALL OF THE I/O'S TOGGLE IN THIS PROGRAM.  MAKE SURE
//    THIS WILL NOT DAMAGE YOUR HARDWARE BEFORE RUNNING THIS
//    EXAMPLE.
//
//    Monitor desired pins on an oscilloscope.
//
//    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:
//
//     Three different examples are included. Select the example 
//     (data, set/clear or toggle) to execute before compiling using
//     the #define statements found at the top of the code.   
//
//
//     Toggle all of the GPIO PORT pins 
//        
//    The pins can be observed using Oscilloscope.  
// 
//
//###########################################################################
// $TI Release: 2833x/2823x Header Files V1.32 $
// $Release Date: June 28, 2010 $
//###########################################################################

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
#include "math.h"
// Select the example to compile in.  Only one example should be set as 1
// the rest should be set as 0.
#define EXAMPLE1 1  // Use DATA registers to toggle I/O's
//#define EXAMPLE2 0  // Use SET/CLEAR registers to toggle I/O's
//#define EXAMPLE3 0  // Use TOGGLE registers to toggle I/O's

float t,ton,d,d1,dr,f;//t = Switching period,dr = duty-ratio,f = frequency
// Prototype statements for functions found within this file.
void delay_loop(void); //decides the ton period of pulse
void delay_loop1(void);//decides the pulse will remain 'zero
void Gpio_select(void);
void Gpio_example1(void);
//void Gpio_example2(void);
//void Gpio_example3(void);

void main(void)
{

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
   InitSysCtrl();
   
// Step 2. Initalize 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
 
// For this example use the following configuration:
   Gpio_select();	  

// 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 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();

	
// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
	
// Step 5. User specific code:
	
#if EXAMPLE1

    // This example uses DATA registers to toggle I/O's
    Gpio_example1();

#endif  // - EXAMPLE1

#if EXAMPLE2

    // This example uses SET/CLEAR registers to toggle I/O's
    Gpio_example2();
    
#endif

#if EXAMPLE3

    // This example uses TOGGLE registers to toggle I/O's
    Gpio_example3();
    
#endif

} 	
//default values
f=50;
t=1/f;
dr=1;
d=dr*t;
ton=d;
d1=t-d;


void delay_loop()
{
    volatile long i;
    for (i = 0; i < d; i++) {}
}

void delay_loop1()
{
    volatile long i;
    for (i = 0; i < d1; i++) {}
}


void Gpio_example1(void)
{ 
   // Example 1:
   // Toggle I/Os using DATA registers

   for(;;)
   {   
       GpioDataRegs.GPADAT.bit.GPIO1    = 1;
   //    GpioDataRegs.GPBDAT.all    =0x0000000A;
       
       delay_loop();

       GpioDataRegs.GPADAT.bit.GPIO1    = 0;
    //   GpioDataRegs.GPBDAT.all    =0x00000005;
    
       delay_loop1();
    }
}

//void Gpio_example2(void)
//{
   // Example 2:
   // Toggle I/Os using SET/CLEAR registers
//   for(;;)
//   {
   
 //      GpioDataRegs.GPASET.all    =0xAAAAAAAA;
//       GpioDataRegs.GPACLEAR.all  =0x55555555;
 ///
//       GpioDataRegs.GPBSET.all    =0x0000000A;
//       GpioDataRegs.GPBCLEAR.all  =0x00000005;
              
//       delay_loop();

 //      GpioDataRegs.GPACLEAR.all    =0xAAAAAAAA;
  //     GpioDataRegs.GPASET.all      =0x55555555;

  //     GpioDataRegs.GPBCLEAR.all    =0x0000000A;
  //     GpioDataRegs.GPBSET.all      =0x00000005;
 //
    //   delay_loop();
   
   // }
//}

//void Gpio_example3(void)
//{
   // Example 2:
   // Toggle I/Os using TOGGLE registers

   // Set pins to a known state
   
 //     GpioDataRegs.GPASET.all    =0xAAAAAAAA;
 //     GpioDataRegs.GPACLEAR.all  =0x55555555;
 //
 //     GpioDataRegs.GPBSET.all    =0x0000000A;
//      GpioDataRegs.GPBCLEAR.all  =0x00000005;

   // Use TOGGLE registers to flip the state of
   // the pins. 
   // Any bit set to a 1 will flip state (toggle)
   // Any bit set to a 0 will not toggle.   

  // for(;;)
//   {
 //     GpioDataRegs.GPATOGGLE.all =0xFFFFFFFF;
 //     GpioDataRegs.GPBTOGGLE.all =0x0000000F;
   //   delay_loop();
  //  }
//}



void Gpio_select(void)
{

   
    EALLOW;
	GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0;  //  GPIO
//	GpioCtrlRegs.GPAMUX2.all = 0x00000000;  // All GPIO
//	GpioCtrlRegs.GPAMUX1.all = 0x00000000;  // All GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO1 = 1;   //  output
 //   GpioCtrlRegs.GPBDIR.all = 0x0000000F;   // All outputs
    EDIS;
     
}     
//===========================================================================
// No more.
//===========================================================================


2. Using CPU timer interrupt

In this i wuld be using the interrupts to set the GPIO pins to high or low as per the duty ratio required by the user.

Here,I am not clear about timer period and system clock settings.How do we set the TPRD and its formula?

please answer the querry.Your help would be appreciated.

Thanks

Sneha Thakur

  • Hi Sneha,

    Before discussion on the above topics, is there any particular reason why you're not considering ePWM module?

    Regards,

    Gautam

  • Hi

    No particular reason.Just wanted to have  a grip over the way programs are written into DSP.The ePWM modules example programs are already existing which would require lilttle modifications.

    Thanks

    Sneha 

  • gautam

    Can you please help me understand the timer period setting and how the system clock is set?

    thanks

    sneha

  • Sneha Thakur said:
    Can you please help me understand the timer period setting and how the system clock is set?

    I'm not sure whether I got your query but according to what I understood:

    You've an inbuilt function to take care of CPUtimer period

    // 150MHz CPU Freq, 1 second Period (in uSeconds)
    
       ConfigCpuTimer(&CpuTimer0, 150, 1000000);

    I hope this is what you're seeking for.

    Regards,

    Gautam

  • Hi gautam

    I know this one.but how do i change it?

    What I aim is to use the CPU Timer 0 and timer 1 program the interrupts as per my requirement to produce a pulse output.Where I should be able to change the sampling period and the pulse width.

    Say whenever interrupt increments the count for Timer0 GPIOpin should set to 1 and then interrupt 2 for Timer1 should increment timer1 count after ton(i.e the pulse width) and set the GPIO pin to low.

    How do i set the TPRD register which has been set to maximum in CPU timer  interrupt program?

    thanks

    Sneha

  • Hi

    I am attaching here a text document for a program to generate pulse using CPUtimers.

    8585.cpu_timer_pulse.txt
    //###########################################################################
    //
    // FILE:    Example_2833xLedBlink.c
    //
    // TITLE:   DSP2833x eZdsp LED Blink Getting Started Program.
    //
    // ASSUMPTIONS:
    //
    //    This program requires the DSP2833x header files.
    //
    //
    //    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 configures CPU Timer0 for a period, and sets and clears the GPIO31
    //    LED on the 2833x eZdsp once per interrupt. For testing purposes, this example
    //    also increments a counter each time the timer asserts an interrupt.
    //
    //       Watch Variables:
    //          CpuTimer0.InterruptCount
    //
    //       Monitor the GPIO31 LED blink on (for GPASET) and off (for GPACLEAR) on the 2833x eZdsp.
    //
    //###########################################################################
    // $TI Release: 2833x/2823x Header Files and Peripheral Examples V133 $
    // $Release Date: June 8, 2012 $
    //###########################################################################
    
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    #include <math.h>
    // Prototype statements for functions found within this file.
    interrupt void cpu_timer0_isr(void);
    float d,t;
    
    void main(void)
    {
    
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2833x_SysCtrl.c file.
       InitSysCtrl();
    
    // Step 2. Initalize 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 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;
    
       EDIS;    // This is needed to disable write to EALLOW protected registers
    
    // Step 4. Initialize the Device Peripheral. This function can be
    //         found in DSP2833x_CpuTimers.c
       InitCpuTimers();   // For this example, only initialize the Cpu Timers
    
    #if (CPU_FRQ_150MHZ)
    // Configure CPU-Timer 0 to interrupt every 1s:
    // 150MHz CPU Freq, Period is in uSeconds
       ConfigCpuTimer(&CpuTimer0, 150, 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 DSP2833x_CpuTimers.h), the
    // below settings must also be updated.
    
       CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
    
    // Step 5. User specific code, enable interrupts:
    
    // Configure GPIO32 as a GPIO output pin
       EALLOW;
       GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0;
       GpioCtrlRegs.GPADIR.bit.GPIO31 = 1;
         EDIS;
    
    // Enable CPU INT1 which is connected to CPU-Timer 0:
       IER |= M_INT1;
    
    
    // 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(;;);
    }
    
    void delay_loop()
    {
       volatile long i;
      for (i = 0; i <= t; i++) {}
    
    }
    
    		interrupt void cpu_timer0_isr(void)
    		{
    			CpuTimer0.InterruptCount++;
    			   GpioDataRegs.GPADAT.bit.GPIO31 = 1; // Sets the GPIO31 to high once per interrupt for the time t provided by delay loop.
    			   delay_loop();
    			  GpioDataRegs.GPADAT.bit.GPIO31 = 0;// clears the GPIO31 to low once per interrupt after delay loop is over and stays there till interrupt is encountered again.
    
    			   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;// Acknowledge this interrupt to receive more interrupts from group 1
    
    		}
    
    	//===========================================================================
    // No more.
    //===========================================================================
    

    Can anyone please suggest how can I set the variable 't' in the delay loop in microseconds?

    thanks

    Sneha

  • Hi,

    It would be much easier to directly use the DELAY_US macro.

    For this you need to add the file called DSP2803x_usDelay.asm and include the headers DSP2803x_Examples.h and DSP2803x_GlobalPrototypes.h

    Alternatively you could add the asm file but merely add the following declaration to your code:

    #define CPU_RATE   16.667L   // for a 60MHz CPU clock speed (SYSCLKOUT)
    #define DELAY_US(A)  DSP28x_usDelay((long)((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L)
    extern void DSP28x_usDelay(long cycle);
    

     Then you can use it this way:

    DELAY_US(4500) // 4.5ms delay

  • Hi Pierre

    Thanks for your reply.

    I tried doing what you suggested.But I am unable to add delay.asm file in the program.S ee the attached screenshot.

  • Hi Sneha,

    1 The file DSP2833x_usDelay.asm is presented at your project already and you can use DELAY_US macro now. Look at your screenshot carefully:

    2 I suspect this thread will useful for your issue.

    Regards,

    Igor

  • I have a similar desire and I can think of one reason not to use the ePWM....

    It appears the action qualifyer can only take 1 action per timebase period in a PWM even when set in immediate mode. Therefore if you have a list of toggle times all of which are < your timebase period you cannot load these consecutively into the CMPA (for exmple via DMA) and have the action qualifier toggle at all these times. What appears to happen is that the DMA will load on all the matches but no actions are taken on each match until the period counter rolls over. Is this correct?

    I tried it without success. I had set up a DMA to load the values of CMPA in a PWM when the compare match happens. The values all do get loaded but the output doesn't appear to toggle on all the matches as it was set to do.

    Now I am moving towards timers as Sneha suggests.

  • Hi Igor

    Thanks for pointing out.

    It's working now.

    Hi Bradford

    I agree with you.

    Thanks

    Sneha

  • Hi

    I have one querry,What is the use of PRD register which has been set to  '"CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;""

    in DSP2833xCpuTimers.c.

    How and when is it required to change?

    Also,What if I want to generate a square wave with both positive and negative halves?

    Thanks

    Sneha

  • Hi, Sneha,

    maybe the following description will answer your question

    Regards,

    Igor

  • Hi Igor

    Thanks for your instant replies.

    But I had already read this datasheet and I am still not clear.Probably If you can help undertsand me with an example.

    Thanks

    Sneha

  • Hi, Sneha,

    please pay attention to this function 

    void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)

    for example, from this file

    c:\ti\controlSUITE\device_support\f2833x\v133\DSP2833x_common\source\

    0675.DSP2833x_CpuTimers.c
    //###########################################################################
    //
    // FILE:    DSP2833x_CpuTimers.c
    //
    // TITLE:   CPU 32-bit Timers Initialization & Support Functions.
    //
    // NOTES:   CpuTimer2 is reserved for use with DSP BIOS and
    //          other realtime operating systems.
    //
    //          Do not use these this timer in your application if you ever plan
    //          on integrating DSP-BIOS or another realtime OS.
    //
    //###########################################################################
    // $TI Release: 2833x/2823x Header Files and Peripheral Examples V133 $
    // $Release Date: June 8, 2012 $
    //###########################################################################
    
    #include "DSP2833x_Device.h"     // Headerfile Include File
    #include "DSP2833x_Examples.h"   // Examples Include File
    
    struct CPUTIMER_VARS CpuTimer0;
    
    // When using DSP BIOS & other RTOS, comment out CPU Timer 2 code.
    struct CPUTIMER_VARS CpuTimer1;
    struct CPUTIMER_VARS CpuTimer2;
    
    //---------------------------------------------------------------------------
    // InitCpuTimers:
    //---------------------------------------------------------------------------
    // This function initializes all three CPU timers to a known state.
    //
    void InitCpuTimers(void)
    {
        // CPU Timer 0
        // Initialize address pointers to respective timer registers:
        CpuTimer0.RegsAddr = &CpuTimer0Regs;
        // Initialize timer period to maximum:
        CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;
        // Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
        CpuTimer0Regs.TPR.all  = 0;
        CpuTimer0Regs.TPRH.all = 0;
        // Make sure timer is stopped:
        CpuTimer0Regs.TCR.bit.TSS = 1;
        // Reload all counter register with period value:
        CpuTimer0Regs.TCR.bit.TRB = 1;
        // Reset interrupt counters:
        CpuTimer0.InterruptCount = 0;
    
    
    // CpuTimer2 is reserved for DSP BIOS & other RTOS
    // Do not use this timer if you ever plan on integrating
    // DSP-BIOS or another realtime OS.
    
        // Initialize address pointers to respective timer registers:
        CpuTimer1.RegsAddr = &CpuTimer1Regs;
        CpuTimer2.RegsAddr = &CpuTimer2Regs;
        // Initialize timer period to maximum:
        CpuTimer1Regs.PRD.all  = 0xFFFFFFFF;
        CpuTimer2Regs.PRD.all  = 0xFFFFFFFF;
        // Make sure timers are stopped:
        CpuTimer1Regs.TCR.bit.TSS = 1;
        CpuTimer2Regs.TCR.bit.TSS = 1;
        // Reload all counter register with period value:
        CpuTimer1Regs.TCR.bit.TRB = 1;
        CpuTimer2Regs.TCR.bit.TRB = 1;
        // Reset interrupt counters:
        CpuTimer1.InterruptCount = 0;
        CpuTimer2.InterruptCount = 0;
    
    }
    
    //---------------------------------------------------------------------------
    // ConfigCpuTimer:
    //---------------------------------------------------------------------------
    // This function initializes the selected timer to the period specified
    // by the "Freq" and "Period" parameters. The "Freq" is entered as "MHz"
    // and the period in "uSeconds". The timer is held in the stopped state
    // after configuration.
    //
    void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
    {
        Uint32  temp;
    
        // Initialize timer period:
        Timer->CPUFreqInMHz = Freq;
        Timer->PeriodInUSec = Period;
        temp = (long) (Freq * Period);
        Timer->RegsAddr->PRD.all = temp;
    
        // Set pre-scale counter to divide by 1 (SYSCLKOUT):
        Timer->RegsAddr->TPR.all  = 0;
        Timer->RegsAddr->TPRH.all  = 0;
    
        // Initialize timer control register:
        Timer->RegsAddr->TCR.bit.TSS = 1;      // 1 = Stop timer, 0 = Start/Restart Timer
        Timer->RegsAddr->TCR.bit.TRB = 1;      // 1 = reload timer
        Timer->RegsAddr->TCR.bit.SOFT = 1;
        Timer->RegsAddr->TCR.bit.FREE = 1;     // Timer Free Run
        Timer->RegsAddr->TCR.bit.TIE = 1;      // 0 = Disable/ 1 = Enable Timer Interrupt
    
        // Reset interrupt counter:
        Timer->InterruptCount = 0;
    }
    
    //===========================================================================
    // End of file.
    //===========================================================================
    

    and you can see the following lines:

    Uint32 temp;

    // Initialize timer period:
    Timer->CPUFreqInMHz = Freq;
    Timer->PeriodInUSec = Period;
    temp = (long) (Freq * Period);
    Timer->RegsAddr->PRD.all = temp;

    Regards,

    Igor