This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320F28027F: CODE FOR SINE WAVE

Part Number: TMS320F28027F
Other Parts Discussed in Thread: C2000WARE

Tool/software: Code Composer Studio

Hello Everyone,

Hope you are Doing Well,

I have Tried to Write a code for a sine wave generation using look up table which is attached below,Can anyone please help in telling whether it is correct or wrong as this is my first time with interrupt ,So is anyone can give any suggestion to optimise this code or any correction it will be really grateful.This 50Hz sine generation using 20kHz ePWM signal.

Also there are some warning which ccs is showing i have mentioned against the line in comment which i am not able to solve.

It will be really great if someone can help.

Thanks in Advance

#include "DSP28x_Project.h"

#define Sine_TABLE_LENGTH 100
#define EPWM1_TIMER_TBPRD  1500

void GPIO_SELECT(void);
void INIT_ePWM1(void);
__interrupt void epwm1_int_isr(void);

#pragma DATA_SECTION(SineTable,"SineTableSection")

uint32_t SineTable[Sine_TABLE_LENGTH]={
 0x00000000,0x41bc646b,0x423c5e7a,0x428d3f6d,0x42bc46b4,0x42eb421a,0x430d1754,0x432484b3,0x433be7b1,0x43533ed4,0x436a88a2,0x4380e1d2,0x438c7731,0x439803b2,0x43a3869d,0x43aeff36,0x43ba6cc3,0x43c5ce8e,0x43d123dd,0x43dc6bfa,0x43e7a62e,0x43f2d1c4,0x43fdee08,0x44047d23,0x4409fae6,0x440f6ff4,0x4414dbf5,0x441a3e91,0x441f9771,0x4424e640,0x442a2aa7,0x442f6451,0x443492ea,0x4439b61e,0x443ecd9a,0x4443d90c,0x4448d822,0x444dca8c,0x4452affa,0x4457881c,0x445c52a4,0x44610f46,0x4465bdb4,0x446a5da3,0x446eeec8,0x447370d5,0x4477e38e,0x447c469f,0x44804ce2,0x44826e5d,0x4484879c,0x4486987e,0x4488a0e3,0x448aa0a8,0x448c97ae,0x448e85d4,0x44906afd,0x44924709,0x449419d9,0x4495e352,0x4497a355,0x449959c6,0x449b068b,0x449ca987,0x449e42a1,0x449fd1be,0x44a156c5,0x44a2d19e,0x44a44231,0x44a5a867,0x44a70429,0x44a85561,0x44a99bf9,0x44aad7de,0x44ac08fb,0x44ad2f3d,0x44ae4a92,0x44af5ae7,0x44b0602b,0x44b15a4f,0x44b24941,0x44b32cf4,0x44b40558,0x44b4d260,0x44b593ff,0x44b64a29,0x44b6f4d3,0x44b793f1,0x44b82779,0x44b8af63,0x44b92ba6,0x44b99c39,0x44ba0116,0x44ba5a36,0x44baa794,0x44bae92b,
 0x44bb1ef7,0x44bb48f4,0x44bb6720,0x44bb7978,0x44bb7ffc};  //#1238-D excess initializers are ignored


unsigned long IntCount;

int main(void)
{
   #ifdef _FLASH
     memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif

   InitSysCtrl();

   GPIO_SELECT();
   DINT;

   InitPieCtrl();

   IER = 0x0000;
   IFR = 0x0000;

   InitPieVectTable();

   EALLOW;
   PieVectTable.EPWM1_INT = &epwm1_int_isr;
   EDIS;

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

   INIT_ePWM1();

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

   IntCount = 0;
   IER |= M_INT2;

   PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
   PieCtrlRegs.PIEIER2.bit.INTx2 = 1;
   PieCtrlRegs.PIEIER2.bit.INTx3 = 1;

   EINT;
   ERTM;

   for(;;)
      {
          __asm("          NOP");
      }
}

void GPIO_SELECT(void)
{
    EALLOW;
    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;
    GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;

    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;

    GpioDataRegs.GPADAT.bit.GPIO0= 1;
    GpioDataRegs.GPADAT.bit.GPIO1= 1;

    EDIS;
}
void INIT_ePWM1(void)
{
    EPwm1Regs.TBPRD= EPWM1_TIMER_TBPRD ;
    EPwm1Regs.TBPHS.half.TBPHS= 0;
    EPwm1Regs.TBCTR= 0x0000;
    EPwm1Regs.CMPA.half.CMPA = SineTable[IntCount] ;
    EPwm1Regs.TBCTL.bit.CTRMODE = 0x2;
    EPwm1Regs.TBCTL.bit.PHSEN=0x0;
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x0;
    EPwm1Regs.TBCTL.bit.CLKDIV = 0x0;
    EPwm1Regs.TBCTL.bit.PRDLD=0x0;
    EPwm1Regs.TBCTL.bit.SYNCOSEL=0x1;
    EPwm1Regs.ETSEL.bit.INTSEL=0x1;
    EPwm1Regs.ETSEL.bit.INTEN=0x1;
    EPwm1Regs.ETPS.bit.INTPRD=0x1;
    EPwm1Regs.ETPS.bit.INTCNT=0x1;

    EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0x0;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = 0x0;

    EPwm1Regs.AQCTLA.bit.ZRO = 0x2;
    EPwm1Regs.AQCTLA.bit.CAU = 0x1;
    EPwm1Regs.AQCTLA.bit.CAD = 0x1;
};

__interrupt void epwm1_int_isr()
{
    if( IntCount < 100)
    {
       IntCount++;
    }
    else
        IntCount = 0;
};



   

  • Rahul,

    your setup code looks reasonable to me, does your code enter your 'epwm1_int-isr' ISR? Simply place a breakpoint in the ISR to check.

    It also appear that you forgot to acknowledge your interrupt, so it will trigger and run once. After that since the interrupt hasn't been acknowledged it will never reenter the ISR.

    A good example of a PWM ISR can be found in C2000Ware here: C:\ti\c2000\C2000Ware_2_00_00_03\device_support\f2802x\examples\structs\epwm_timer_interrupts

    Regards,
    Cody 

  • I see nothing obviously wrong with your code, though I'm not going through it in detail.

    The warning is because you have declared an array with 100 elements, then specified 101 initializers for it.  The compiler will ignore the last initializer, which is probably not what you want.

    Regards,

    Richard

  • Thanks Richard For you Reply, I got the point and made the necessary changes.

  • Thanks Cody for looking into it ,

    I got you your point but Can you please help in deep understanding of this Interrupt function as this is my first time working with Interrupt ,though I understand it  but not able to implement as i am able to understand how actually this works.

    Any help will be great .

    Thank You 

    Rahul   

  • Rahul,

    In general I would say that our interrupts come from an peripheral , go through the 'PIE', and then make it to the C28x core.

    The peripheral simply raises a flag indicating some event occurred.

    The PIE (Peripheral Interrupt Expansion) then, if the interrupt is enabled brings this signal closer to the CPU. The PIE is needed because the Core has a limited number of interrupt lines, the PIE enables many different signals to share the same interrupt line.

    The C28x core,  assuming the global interrupts are enabled, then preforms a program counter jump depending on the value that is found inside of PIE vector table. The core does some context storing, executes the ISR and then a context restore.

    I recognize that the above is brief, the following link should take you to a good training. Look at section 5 for more information on interrupts.

    https://training.ti.com/c2000-f2802x-microcontroller-workshop?context=1137791-1137785

    It would also be helpful for you to read through the TRM's interrupt section.

    Hope it helps,
    Cody

  • Hey Cody,

    I checked the output of the above code but nothing is obtained as output and i guess you were right the Code doesn't enter the ISR,after your suggestion i made a few changes ,so new code is written below.

    Can you please help here and tell what's the problem and what can i d to solve it?

    Thanks

    Rahul

    #include "DSP28x_Project.h"
    
    #define Sine_TABLE_LENGTH 101
    #define EPWM1_TIMER_TBPRD  1500
    
    void GPIO_SELECT(void);
    void INIT_ePWM1(void);
    __interrupt void epwm1_int_isr(void);
    
    #pragma DATA_SECTION(SineTable,"SineTableSection")
    
    uint32_t SineTable[Sine_TABLE_LENGTH]={
     0x00000000,0x41bc646b,0x423c5e7a,0x428d3f6d,0x42bc46b4,0x42eb421a,0x430d1754,0x432484b3,0x433be7b1,0x43533ed4,0x436a88a2,0x4380e1d2,0x438c7731,0x439803b2,0x43a3869d,0x43aeff36,
     0x43ba6cc3,0x43c5ce8e,0x43d123dd,0x43dc6bfa,0x43e7a62e,0x43f2d1c4,0x43fdee08,0x44047d23,0x4409fae6,0x440f6ff4,0x4414dbf5,0x441a3e91,0x441f9771,0x4424e640,0x442a2aa7,0x442f6451,
     0x443492ea,0x4439b61e,0x443ecd9a,0x4443d90c,0x4448d822,0x444dca8c,0x4452affa,0x4457881c,0x445c52a4,0x44610f46,0x4465bdb4,0x446a5da3,0x446eeec8,0x447370d5,0x4477e38e,0x447c469f,
     0x44804ce2,0x44826e5d,0x4484879c,0x4486987e,0x4488a0e3,0x448aa0a8,0x448c97ae,0x448e85d4,0x44906afd,0x44924709,0x449419d9,0x4495e352,0x4497a355,0x449959c6,0x449b068b,0x449ca987,
     0x449e42a1,0x449fd1be,0x44a156c5,0x44a2d19e,0x44a44231,0x44a5a867,0x44a70429,0x44a85561,0x44a99bf9,0x44aad7de,0x44ac08fb,0x44ad2f3d,0x44ae4a92,0x44af5ae7,0x44b0602b,0x44b15a4f,
     0x44b24941,0x44b32cf4,0x44b40558,0x44b4d260,0x44b593ff,0x44b64a29,0x44b6f4d3,0x44b793f1,0x44b82779,0x44b8af63,0x44b92ba6,0x44b99c39,0x44ba0116,0x44ba5a36,0x44baa794,0x44bae92b,
     0x44bb1ef7,0x44bb48f4,0x44bb6720,0x44bb7978,0x44bb7ffc};
    
    unsigned int IntCount;
    char flag;
    
    int main(void)
    {
       #ifdef _FLASH
         memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
        #endif
    
       InitSysCtrl();
    
       GPIO_SELECT();
       DINT;
    
       InitPieCtrl();
    
       IER = 0x0000;
       IFR = 0x0000;
    
       InitPieVectTable();
    
       // Interrupts that are used in this example are re-mapped to
       EALLOW;
       PieVectTable.EPWM1_INT = &epwm1_int_isr;
       EDIS;
    
       EALLOW;
       SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
       EDIS;
    
       INIT_ePWM1();
    
       EALLOW;
       SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
       EDIS;
    
       IntCount = 0;
       flag = true;
    
       //Enable CPU INT3 which is connected to EPWM1-6 INT:
       IER |= M_INT2;
    
       PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
       PieCtrlRegs.PIEIER2.bit.INTx2 = 1;
       PieCtrlRegs.PIEIER2.bit.INTx3 = 1;
    
       EINT;
       ERTM;
    
       for(;;)
          {
              __asm("          NOP");
          }
    }
    
    void GPIO_SELECT(void)
    {
        EALLOW;
        GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;
        GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;
    
        GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;
    
        GpioDataRegs.GPADAT.bit.GPIO0= 1;
        GpioDataRegs.GPADAT.bit.GPIO1= 1;
    
        EDIS;
    }
    void INIT_ePWM1(void)
    {
        EPwm1Regs.TBPRD= EPWM1_TIMER_TBPRD ;
        EPwm1Regs.TBPHS.half.TBPHS= 0;
        EPwm1Regs.TBCTR= 0x0000;
        EPwm1Regs.CMPA.half.CMPA = SineTable[IntCount] ;
        EPwm1Regs.TBCTL.bit.CTRMODE = 0x2;
        EPwm1Regs.TBCTL.bit.PHSEN=0x0;
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x0;
        EPwm1Regs.TBCTL.bit.CLKDIV = 0x0;
        EPwm1Regs.TBCTL.bit.PRDLD=0x0;
        EPwm1Regs.TBCTL.bit.SYNCOSEL=0x1;
        EPwm1Regs.ETSEL.bit.INTSEL=0x1;
        EPwm1Regs.ETSEL.bit.INTEN=0x1;
        EPwm1Regs.ETPS.bit.INTPRD=0x1;
        EPwm1Regs.ETPS.bit.INTCNT=0x1;
    
        EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0x0;
        EPwm1Regs.CMPCTL.bit.LOADAMODE = 0x0;
    
        EPwm1Regs.AQCTLA.bit.ZRO = 0x2;
        EPwm1Regs.AQCTLA.bit.CAU = 0x1;
        EPwm1Regs.AQCTLA.bit.CAD = 0x1;
    };
    
    __interrupt void epwm1_int_isr()
    {
        if( flag == true && IntCount < 101)
        {
           IntCount++;
           if (IntCount == 101)
           {
               flag = false;
           }
        }
        else
        {
            flag = false;
            IntCount--;
            if (IntCount == 0)
              {
                 flag = true;
              }
        }
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    };
    
    
    
    

     

  • Rahul,

    I see a few things that you will need to check.

    1. Is the interrupt flag being raised by the ePWM module?
    2. Is the PIE setup to enable said flag?
    3. Are interrupts globally enabled?
    4. Have you correctly loaded the PIE vector table with the address of your interrupt?

    If you need more information about these topics please go through the training and TRM sections referenced in my previous post. 

    Regards,
    Cody