MPC5606B eMIOS0 PWM generation Phase lag?

cancel
Showing results for 
Search instead for 
Did you mean: 

MPC5606B eMIOS0 PWM generation Phase lag?

Jump to solution
799 Views
akshaydaga
Contributor III

I have written a program to Generate 6 PWM pulse of 20kHz  and Initial DutyCycle = 10% at

eMIOS0_1 => PA[1]                 eMIOS0_2 => PA[2]

eMIOS0_3 => PA[3]                 eMIOS0_4 => PA[4]

eMIOS0_5 => PA[5]                 eMIOS0_6 => PA[6]

 

Initial Duty_Cycle = 10%

Press Switch1 => PE[64], Duty_Cycle = 20%

Press Switch2 => PE[65], Duty_Cycle = 40%

Press Switch3 => PE[66], Duty_Cycle = 60%

Press Switch4 => PE[67], Duty_Cycle = 80%

 

I checked the Output on DSO.

 

Even though I am Enabling all the eMIOS channel at the same time, but still I am getting 1uSec phase lag on PWM at CH5 PA[5] and CH6 PA[6]. (PWM at CH[1] to CH[4] are IN-Phase i.e. No Phase lag)

Why such phase lag is happening?

 

I tried to change sequence of of updating (CADR, CBDR ,CCR) Registers of different channels , But couldn't see any logical change?

 

So, the question is,

1. Why such phase lag is occurring?

2. How to get rid of this phase lag?

 

My Code is as follows:

********************************************************************************************************************************************

/********************************************************************

20KHz PWM at

eMIOS0_1 => PA[1], eMIOS0_2 => PA[2],

eMIOS0_3 => PA[3], eMIOS0_4 => PA[4],

eMIOS0_5 => PA[5], eMIOS0_6 => PA[6].  

 

Initial Duty_Cycle = 10%

Press Switch1, Duty_Cycle = 20%

Press Switch2, Duty_Cycle = 40%

Press Switch3, Duty_Cycle = 60%

Press Switch4, Duty_Cycle = 80%

Coding Done by Akshay P. Daga

Date: 26/03/2016

*********************************************************************/

/*********************************************************************

  Frequency Calculation of PWM:

   For "x" Hz Frequency, B_VAL = 1/[(x)*10^-6]

  Duty Cycle Calculation of PWM:

   For "y" % Duty Cycle, A_VAL = (y)*100/(x)

*********************************************************************/

 

 

#include "MPC5606B.h"

#define SW_1 64

#define SW_2 65

#define SW_3 66

#define SW_4 67

 

 

#define CH_1 1

#define CH_2 2

#define CH_3 3

#define CH_4 4

#define CH_5 5

#define CH_6 6

 

 

#define eMIOS0CH0 0

#define eMIOS0CH1 1

#define eMIOS0CH2 2

#define eMIOS0CH3 3

#define eMIOS0CH4 4

#define eMIOS0CH5 5

#define eMIOS0CH6 6

#define eMIOS0CH7 7

#define eMIOS0CH8 8

#define eMIOS0CH9 9

 

 

#define B_VAL 50

#define A_VAL1 10

#define A_VAL2 20

#define A_VAL3 30

#define A_VAL4 40

#define INITIAL_A_VAL 5

 

 

#define GPIO_INPUT 0x0101

 

 

uint16_t sw1State;

uint16_t sw2State;

uint16_t sw3State;

uint16_t sw4State;

 

 

//uint32_t currDutyCycle;

 

 

void InitModesAndClks(void);

void eMIOS_Init(void);

void Init_GPIO(void);

//void switch_to_25_10ms(void);

//void switch_to_75_20ms(void);

void switch_PWM_DutyCycle(uint32_t);

void main(void);

 

 

/* Enter RUN0 with PLL as sys clk (64 MHz) with 8 MHz crystal reference. */

void InitModesAndClks(void) {

      ME.MER.R = 0x0000001D;          /* Enable DRUN, RUN0, SAFE, RESET modes */

      CGM.FMPLL_CR.R = 0x01200100;    /* 8MHz xtal: Set PLL0 to 64 MHz */

      ME.RUNPC[0].R = 0x000000FE; /* enable peripherals run in all modes */

      ME.RUN[0].R = 0x001F0074;       /* RUN0 cfg: IRCON,OSC0ON,PLL0ON,syclk=PLL */

      /* Mode Transition to enter RUN0 mode: */

      ME.MCTL.R = 0x40005AF0;         /* Enter RUN0 Mode & Key */

      ME.MCTL.R = 0x4000A50F;         /* Enter RUN0 Mode & Inverted Key */

      while (ME.GS.B.S_MTRANS) {} ;    /* Wait for mode transition to complete */

      while(ME.GS.B.S_CURRENTMODE != 4) {}; /* Verify RUN0 is the current mode */

}

 

 

void eMIOS_Init(void) //1ms duty cycle 50%

{ EMIOS_0.MCR.R = 0x14004000; //EMIOS Module Configuration Register (EMIOS_MCR)

            /* Module : Enable    */

            /* Global Freeze: Disabled                  */

            /* Global Time Base Enable: Yes             */

            /* Global Prescaler Enable: Yes             */

            /* Global Prescaler Value:   63             */

  //EMIOS_0.MCR.R = 0x14000000; //Prescalar value = 1

  EMIOS_0.MCR.R = 0x14004100; //Prescalar value = 64

  EMIOS_0.OUDR.R = 0x00000000; //EMIOS Output Update Disable Register (EMIOS_OUDR) (EMIOSOUDIS in Reference Manual)

            /* Channel n output is Enabled  */

      // En 

            /*   n = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 */

 

 

 

//CH[1] 

  EMIOS_0.CH[CH_1].CADR.R = 0x000001F4; //Unified Channel 01 Registers  //[16-31]  Channel eMIOS_0_CADR2 Data Register - eMIOS_0_CADR2 : Value = 500

  EMIOS_0.CH[CH_1].CBDR.R = 0x000003E8; //Unified Channel 01 Registers  //[16-31]  Channel eMIOS_0_CBDR2 Data Register - eMIOS_0_CBDR2 : Value = 1000

  EMIOS_0.CH[CH_1].CCR.R = 0x02000658; //Active High PWM, Internal Prescaler = 1

  //EMIOS_0.CH[CH_1].CCR.R = 0x020006D8; //Active Low PWM //Unified Channel 02 Registers (EMIOSC[n])

            /* Channel Control Register                 */

            /* Freeze Enable : Normal operation         */

            /* Prescaler Divide Ratio : 1             */

            /* Prescaler Enable : Enable                */

            /* Flag generation Request: Assigned to Interrupt */

            /* Input Filter: Not Applicable                */

            /* Filter clock select : Prescaler clock    */

            /* Flag Enable : IRQ/DMA not generated      */

            /* Force Match A : Disabled                 */

            /* Force Match B : Disabled                 */

            /* Bus Select : Internal counter                */

            /* Edge Selection Bit :Not Applicable                 */

            /* Edge Polarity :Set on Match A = Active Low PWM                  */

            /* Mode : Output Pulse Width and Frequency M*/

            /* odulation Buffered                       */

 

  //EMIOS_0.CH[CH_1].CCR.R = 0x0E000658; //Active High PWM, Internal Prescalar = 4

 

 

 

  //CH[2]

    EMIOS_0.CH[CH_2].CADR.R = 0x000001F4; //A_VAL= 500  -> 50%

    EMIOS_0.CH[CH_2].CBDR.R = 0x000003E8; //B_VAL= 1000 -> 1KHz

    EMIOS_0.CH[CH_2].CCR.R = 0x02000658;  //Active High PWM, Internal Prescaler = 1

  //CH[3]

    EMIOS_0.CH[CH_3].CADR.R = 0x000001F4; //A_VAL= 500  -> 50%

    EMIOS_0.CH[CH_3].CBDR.R = 0x000003E8; //B_VAL= 1000 -> 1KHz

    EMIOS_0.CH[CH_3].CCR.R = 0x02000658;  //Active High PWM, Internal Prescaler = 1

  //CH[4]

    EMIOS_0.CH[CH_4].CADR.R = 0x000001F4; //A_VAL= 500  -> 50%

    EMIOS_0.CH[CH_4].CBDR.R = 0x000003E8; //B_VAL= 1000 -> 1KHz

    EMIOS_0.CH[CH_4].CCR.R = 0x02000658;  //Active High PWM, Internal Prescaler = 1

  //CH[5]

    EMIOS_0.CH[CH_5].CADR.R = 0x000001F4; //A_VAL= 500  -> 50%

    EMIOS_0.CH[CH_5].CBDR.R = 0x000003E8; //B_VAL= 1000 -> 1KHz

    EMIOS_0.CH[CH_5].CCR.R = 0x02000658;  //Active High PWM, Internal Prescaler = 1      

  //CH[6]

    EMIOS_0.CH[CH_6].CADR.R = 0x000001F4; //A_VAL= 500  -> 50%

    EMIOS_0.CH[CH_6].CBDR.R = 0x000003E8; //B_VAL= 1000 -> 1KHz

    EMIOS_0.CH[CH_6].CCR.R = 0x02000658;  //Active High PWM, Internal Prescaler = 1

 

 

 

 

 

 

 

 

    //EMIOS_0.UCDIS.R = 0x00000000; //EMIOS Channel Disable Register  (EMIOS_UCDIS)

                /* Channel n is Enabled  */

                /*   n = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, */

 

 

    EMIOS_0.UCDIS.R = 0xFFFFFFFF; //All EMIOS Channel Disabled

    EMIOS_0.UCDIS.R &= ~((1<<eMIOS0CH1)|(1<<eMIOS0CH2)|(1<<eMIOS0CH3)|(1<<eMIOS0CH4)|(1<<eMIOS0CH5)|(1<<eMIOS0CH6));

    //eMIOS0_CH1,2,3,4,5,6 are Enabled.

}

 

 

void Init_GPIO(void)

{

  SIU.PCR[SW_1].R = GPIO_INPUT;  //GPIO as Input

  SIU.PCR[SW_2].R = GPIO_INPUT;  //GPIO as Input

  SIU.PCR[SW_3].R = GPIO_INPUT;  //GPIO as Input

  SIU.PCR[SW_4].R = GPIO_INPUT;  //GPIO as Input

 

  SIU.PCR[CH_1].R = 0x0600; //PA=01->AF1, OBE=1

  SIU.PCR[CH_2].R = 0x0600; //PA=01->AF1, OBE=1

  SIU.PCR[CH_3].R = 0x0600; //PA=01->AF1, OBE=1

  SIU.PCR[CH_4].R = 0x0600; //PA=01->AF1, OBE=1

  SIU.PCR[CH_5].R = 0x0600; //PA=01->AF1, OBE=1

  SIU.PCR[CH_6].R = 0x0600; //PA=01->AF1, OBE=1

}

 

 

/*

void switch_to_25_10ms(void) //10ms 25%/75% -> 100Hz

{

  EMIOS_0.CH[CH_2].CADR.R = 0x000009C4; //  [16-31]  Channel eMIOS_0_CADR2 Data Register - eMIOS_0_CADR2 : Value = 2500

  EMIOS_0.CH[CH_2].CBDR.R = 0x00002710; //  [16-31]  Channel eMIOS_0_CBDR2 Data Register - eMIOS_0_CBDR2 : Value = 10000

} */

/*

void switch_to_75_20ms(void) //20ms 75%/25% -> 50Hz

{

  EMIOS_0.CH[CH_2].CADR.R = 0x00003A98; //  [16-31]  Channel eMIOS_0_CADR2 Data Register - eMIOS_0_CADR2 : Value = 500

  EMIOS_0.CH[CH_2].CBDR.R = 0x00004E20; //  [16-31]  Channel eMIOS_0_CBDR2 Data Register - eMIOS_0_CBDR2 : Value = 20000

}

*/

 

 

void switch_PWM_DutyCycle(uint32_t aVal) //1ms 20%/80% -> 1KHz

{

  //CH[1]

   EMIOS_0.CH[CH_1].CADR.R = aVal;

   EMIOS_0.CH[CH_1].CBDR.R = B_VAL;

  //CH[6]

   EMIOS_0.CH[CH_6].CADR.R = aVal;

   EMIOS_0.CH[CH_6].CBDR.R = B_VAL;

  //CH[4]

   EMIOS_0.CH[CH_4].CADR.R = aVal;

   EMIOS_0.CH[CH_4].CBDR.R = B_VAL;

  //CH[5]

   EMIOS_0.CH[CH_5].CADR.R = aVal;

   EMIOS_0.CH[CH_5].CBDR.R = B_VAL; 

  //CH[2]

   EMIOS_0.CH[CH_2].CADR.R = aVal;  // [16-31]  Channel eMIOS_0_CADR2 Data Register - eMIOS_0_CADR2 : Value = 500

   EMIOS_0.CH[CH_2].CBDR.R = B_VAL; // [16-31]  Channel eMIOS_0_CBDR2 Data Register - eMIOS_0_CBDR2 : Value = 10000*/

  //CH[3]

   EMIOS_0.CH[CH_3].CADR.R = aVal;

   EMIOS_0.CH[CH_3].CBDR.R = B_VAL;

 

 

}

 

 

void main(void)

{

  volatile int i = 0;

   InitModesAndClks();

   Init_GPIO();

   eMIOS_Init();

  

   switch_PWM_DutyCycle(INITIAL_A_VAL);

 

   /* Loop forever */

  for (;;) {

    i++;

    sw1State = SIU.GPDI[SW_1].B.PDI;

    sw2State = SIU.GPDI[SW_2].B.PDI;

    sw3State = SIU.GPDI[SW_3].B.PDI;

    sw4State = SIU.GPDI[SW_4].B.PDI;

   

    if(sw1State){

    switch_PWM_DutyCycle(A_VAL1);

    }

    if(sw2State){

    switch_PWM_DutyCycle(A_VAL2);

    }

    if(sw3State){

    switch_PWM_DutyCycle(A_VAL3);

    }

    if(sw4State){

    switch_PWM_DutyCycle(A_VAL4);

    }

  }

}

 

********************************************************************************************************************************************

Original Attachment has been moved to: eMIOS_Testing_APDaga.rar

Labels (1)
1 Solution
414 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

use the Global Time Base Enable bit in MCR to start channels simultaneously.

So clear the GTBE bit at beginning of eMIOS_Init() and set it at the end.

void eMIOS_Init(void) //1ms duty cycle 50%

{

/* Module : Enable    */

/* Global Freeze: Disabled                  */

/* Global Time Base Enable: No             */

/* Global Prescaler Enable: Yes             */

/* Global Prescaler Value:   63             */

EMIOS_0.MCR.R = 0x04003F00;

….

EMIOS_0.MCR.B.GTBE = 1;    // start all channel at the same time

}

BR, Petr

View solution in original post

6 Replies
415 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

use the Global Time Base Enable bit in MCR to start channels simultaneously.

So clear the GTBE bit at beginning of eMIOS_Init() and set it at the end.

void eMIOS_Init(void) //1ms duty cycle 50%

{

/* Module : Enable    */

/* Global Freeze: Disabled                  */

/* Global Time Base Enable: No             */

/* Global Prescaler Enable: Yes             */

/* Global Prescaler Value:   63             */

EMIOS_0.MCR.R = 0x04003F00;

….

EMIOS_0.MCR.B.GTBE = 1;    // start all channel at the same time

}

BR, Petr

414 Views
akshaydaga
Contributor III

Thanks Sir for your Suggestion. It worked for above problem.

But, I have taken 3 External Interrupts, In each of the Interrupt 2 of 6 PWMs are getting enabled and 4 of 6 PWMs getting Disabled. In each interrupt,2 different PWMs are getting Enabled. Now Since I have Enbled GTBE at the end of the EMIOS_Init function and then Enabling and Disabling PWMS in interrupt by setting UCDIS value .

This is introducing Lag in between 2 PWMs.

What is the solution for that?

0 Kudos
414 Views
PetrS
NXP TechSupport
NXP TechSupport

I looks you want to control 3phase motor or something similar.

I guess the usage of the OPWMB mode will be better for you. In this mode channel is running from common counter bus (e.g. counter bus A), so this will ensure a synchronicity on all channels.

To disable certain channels you can just set 0% duty cycle, that’s take effect in next PWM cycle.

Or you can use the OCDIS register to disable the channel.

BR, Petr

414 Views
yanna
Contributor IV

Hi,Petr

I think this font is not easy to read. :smileylaugh:

Best regards!

Yanna

0 Kudos
414 Views
alexvinchev
Contributor V

I believe that solution is the same. At each interrupt you just have to:

1. Stop all PWMs;

2. Reconfigure PWMs (configure PWMs that has not to be started in a way they will not run. This could be done either by disabling PWM in its configuration, either by changing pin mode to GPIO with correct level - 0/1);

3. Start all PWM thru GTBE, which will start only PWMs that has to run, but synchronously;

414 Views
akshaydaga
Contributor III

Thank you sir,
It worked for me. and Phase lag is gone completely.

0 Kudos