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
Solved! Go to Solution.
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
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
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?
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
Hi,Petr
I think this font is not easy to read. :smileylaugh:
Best regards!
Yanna
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;
Thank you sir,
It worked for me. and Phase lag is gone completely.