예제 #1
0
void Atomizer_Init() {
	// Select shunt value based on hardware version
	switch(Dataflash_info.hwVersion) {
		case 101:
		case 108:
			Atomizer_shuntRes = 125;
			break;
		case 103:
		case 104:
		case 105:
		case 106:
			Atomizer_shuntRes = 110;
			break;
		case 107:
		case 109:
			Atomizer_shuntRes = 120;
			break;
		case 110:
		case 111:
			Atomizer_shuntRes = 105;
			break;
		case 100:
		case 102:
		default:
			Atomizer_shuntRes = 115;
			break;
	}

	// Setup control pins
	PC1 = 0;
	GPIO_SetMode(PC, BIT1, GPIO_MODE_OUTPUT);
	PC3 = 0;
	GPIO_SetMode(PC, BIT3, GPIO_MODE_OUTPUT);

	// Both channels powered down
	Atomizer_ConfigureConverters(0, 0);

	// Configure 150kHz PWM
	PWM_ConfigOutputChannel(PWM0, ATOMIZER_PWMCH_BUCK, 150000, 0);
	PWM_ConfigOutputChannel(PWM0, ATOMIZER_PWMCH_BOOST, 150000, 0);

	// Start PWM
	PWM_EnableOutput(PWM0, PWM_CH_0_MASK);
	PWM_EnableOutput(PWM0, PWM_CH_2_MASK);
	PWM_Start(PWM0, PWM_CH_0_MASK);
	PWM_Start(PWM0, PWM_CH_2_MASK);

	// Set duty cycle to zero
	PWM_SET_CMR(PWM0, ATOMIZER_PWMCH_BUCK, 0);
	PWM_SET_CMR(PWM0, ATOMIZER_PWMCH_BOOST, 0);

	Atomizer_targetVolts = 0;
	Atomizer_curCmr = 0;
	Atomizer_curState = POWEROFF;

	// Setup 5kHz timer for negative feedback cycle
	// This function should run during system init, so
	// the user hasn't had time to create timers yet.
	Timer_CreateTimer(5000, 1, Atomizer_TimerCallback, 0);
}
예제 #2
0
uint32_t PWM_ConfigOutputChannelf(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Frequency, float u32DutyCycle)
{
	uint32_t u32Src;
	uint32_t u32PWMClockSrc;
	uint32_t i;
	uint16_t u16Prescale = 1, u16CNR = 0xFFFF;

	if(pwm == PWM0)
		u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM0SEL_Msk;
	else//(pwm == PWM1)
		u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM1SEL_Msk;

	if(u32Src == 0) {
		//clock source is from PLL clock
			u32PWMClockSrc = CLK_GetPLLClockFreq();
	} 
	else {
		//clock source is from PCLK
		SystemCoreClockUpdate();
		u32PWMClockSrc = SystemCoreClock;
	}

	for(u16Prescale = 1; u16Prescale < 0xFFF; u16Prescale++) {
		i = (u32PWMClockSrc / u32Frequency) / u16Prescale;
		if(i > (0x10000))
			continue;
		u16CNR = i;
		break;
	}

	i = u32PWMClockSrc / ((u16Prescale + 1) * u16CNR);
	PWM_SET_PRESCALER(pwm, u32ChannelNum, --u16Prescale);
    /* Set Counter to upcount */
	(pwm)->CTL1 = ((pwm)->CTL1 & ~(PWM_CTL1_CNTTYPE0_Msk << (2 * u32ChannelNum))) | (0UL << (2 * u32ChannelNum));
	(pwm)->CTL1 &= ~(PWM_CTL1_CNTMODE0_Msk << u32ChannelNum);

    if(u32DutyCycle == 100)
    {
        PWM_SET_CMR(pwm, u32ChannelNum, u16CNR);
        PWM_SET_CNR(pwm, u32ChannelNum, --u16CNR);        
    }
    else
    {
	PWM_SET_CMR(pwm, u32ChannelNum, (uint32_t)(u32DutyCycle * (u16CNR + 1) / 100 - 1));
	PWM_SET_CNR(pwm, u32ChannelNum, --u16CNR);
    }

	(pwm)->WGCTL0 = ((pwm)->WGCTL0 & ~(PWM_WGCTL0_ZPCTL0_Msk << (u32ChannelNum * 2 + PWM_WGCTL0_ZPCTL0_Msk)))
                    | (PWM_OUTPUT_HIGH << (u32ChannelNum * 2 + PWM_WGCTL0_ZPCTL0_Pos));
	(pwm)->WGCTL1 = ((pwm)->WGCTL1 & ~(PWM_WGCTL1_CMPUCTL0_Msk << (u32ChannelNum * 2 + PWM_WGCTL1_CMPUCTL0_Pos)))
                    | (PWM_OUTPUT_LOW << (u32ChannelNum * 2 + PWM_WGCTL1_CMPUCTL0_Pos));
	return(i);
}
예제 #3
0
/**
 * Negative feedback iteration to keep the DC/DC converters stable.
 * Takes parameters an an ADC callback.
 * This is an internal function.
 */
static void Atomizer_NegativeFeedback(uint16_t adcValue, uint32_t unused) {
	uint16_t curVolts;

	if(Atomizer_curState == POWEROFF) {
		// Powered off, nothing to do
		return;
	}

	// Calculate current voltage
	curVolts = ATOMIZER_ADC_VOLTAGE(adcValue);
	if(curVolts == Atomizer_targetVolts) {
		// Target reached, nothing to do
		return;
	}

	if(curVolts < Atomizer_targetVolts) {
		if(Atomizer_curState == POWERON_BUCK) {
			if(Atomizer_curCmr == 479) {
				// Reached maximum for buck, switch to boost
				Atomizer_curState = POWERON_BOOST;
				Atomizer_ConfigureConverters(0, 1);
			}
			else {
				// In buck mode, increased duty cycle = increased voltage
				Atomizer_curCmr++;
			}
		}
		else if(Atomizer_curCmr > 80) {
			// Boost duty cycle must be greater than 80
			// In boost mode, decreased duty cycle = increased voltage
			Atomizer_curCmr--;
		}
	}
	else {
		if(Atomizer_curState == POWERON_BOOST) {
			if(Atomizer_curCmr == 479) {
				// Reached minimum for boost, switch to buck
				Atomizer_curState = POWERON_BUCK;
				Atomizer_ConfigureConverters(1, 0);
			}
			else {
				// In boost mode, increased duty cycle = decreased voltage
				Atomizer_curCmr++;
			}
		}
		else {
			if(Atomizer_curCmr <= 10) {
				// Buck duty cycles below 10 are forced to zero
				Atomizer_curCmr = 0;
			}
			else {
				// In buck mode, decreased duty cycle = decreased voltage
				Atomizer_curCmr--;
			}
		}
	}

	// Set new duty cycle
	PWM_SET_CMR(PWM0, Atomizer_curState == POWERON_BUCK ? ATOMIZER_PWMCH_BUCK : ATOMIZER_PWMCH_BOOST, Atomizer_curCmr);
}
예제 #4
0
파일: main.c 프로젝트: brucetsao/Nuvoton
void PWM0_Init()
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init PWM0                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Set PWM0 clock prescaler */
    PWM_SET_PRESCALER(PWM0, 0, 0);

    /* Set up counter type */
    PWM0->CTL1 &= ~PWM_CTL1_CNTTYPEn_Msk;

    /* Set PWM0 timer duty */
    PWM_SET_CMR(PWM0, 0, 360);

    /* Set PWM0 timer period */
    PWM_SET_CNR(PWM0, 0, 720);

    /* PWM period point trigger DAC enable */
    PWM0->DACTRGEN = 0x1 << PWM_DACTRGEN_PTEn_Pos;

    /* Set waveform generation */
    PWM0->WGCTL0 = 0xAAA;//PWM zero point and period point output High.
    PWM0->WGCTL1 = 0x555;//PWM compare down point and  compare up point output Low.

    /* Enable output of all PWM0 channels */
    PWM0->POEN |= PWM_POEN_POENn_Msk;
}
예제 #5
0
/**
 * @brief       PWM0 IRQ Handler
 *
 * @param       None
 *
 * @return      None
 *
 * @details     ISR to handle PWM0 interrupt event
 */
void PWM0_IRQHandler(void)
{
    static int toggle = 0;

    // Update PWM0 channel 0 period and duty
    if(toggle == 0)
    {
        PWM_SET_CNR(PWM0, 0, 99);
        PWM_SET_CMR(PWM0, 0, 39);
    }
    else
    {
        PWM_SET_CNR(PWM0, 0, 399);
        PWM_SET_CMR(PWM0, 0, 199);
    }
    toggle ^= 1;
    // Clear channel 0 period interrupt flag
    PWM_ClearPeriodIntFlag(PWM0, 0);
}
예제 #6
0
//=========================================================================
//----- (00005C4C) --------------------------------------------------------
__myevic__ void InitPWM()
{
	PWM_ConfigOutputChannel( PWM0, BBC_PWMCH_BUCK, BBC_PWM_FREQ, 0 );
	PWM_ConfigOutputChannel( PWM0, BBC_PWMCH_BOOST, BBC_PWM_FREQ, 0 );

	PWM_EnableOutput( PWM0, 1 << BBC_PWMCH_BUCK );
	PWM_EnablePeriodInt( PWM0, BBC_PWMCH_BUCK, 0 );

	PWM_EnableOutput( PWM0, 1 << BBC_PWMCH_BOOST );
	PWM_EnablePeriodInt( PWM0, BBC_PWMCH_BOOST, 0 );

	PWM_Start( PWM0, 1 << BBC_PWMCH_BUCK );
	PWM_Start( PWM0, 1 << BBC_PWMCH_BOOST );

	BoostDuty = 0;
	PWM_SET_CMR( PWM0, BBC_PWMCH_BOOST, 0 );

	BuckDuty = 0;
	PWM_SET_CMR( PWM0, BBC_PWMCH_BUCK, 0 );

	if ( ISVTCDUAL || ISCUBOID || ISCUBO200 || ISRX200S || ISRX23 || ISRX300 )
	{
		PWM_ConfigOutputChannel( PWM0, BBC_PWMCH_CHARGER, BBC_PWM_FREQ, 0 );
		PWM_EnableOutput( PWM0, 1 << BBC_PWMCH_CHARGER );
		PWM_Start( PWM0, 1 << BBC_PWMCH_CHARGER );

		ChargerDuty = 0;
		PWM_SET_CMR( PWM0, BBC_PWMCH_CHARGER, 0 );

		if ( ISCUBO200 || ISRX200S || ISRX23 || ISRX300 )
		{
			MaxChargerDuty = 512;
		}
		else
		{
			MaxChargerDuty = 256;
		}
	}
}
예제 #7
0
void Atomizer_Control(uint8_t powerOn) {
	if((!powerOn && Atomizer_curState == POWEROFF) || (powerOn && Atomizer_curState != POWEROFF)) {
		// Nothing to do
		return;
	}

	if(powerOn) {
		// Start from buck with duty cycle 10
		Atomizer_curCmr = 10;
		Atomizer_ConfigureConverters(1, 0);
		PWM_SET_CMR(PWM0, ATOMIZER_PWMCH_BUCK, Atomizer_curCmr);
		Atomizer_curState = POWERON_BUCK;
	}
	else {
		Atomizer_curState = POWEROFF;
		Atomizer_ConfigureConverters(0, 0);
	}
}
예제 #8
0
void motorsSetRatio(int id, uint16_t u16PulseWidth)
{
#ifdef M451
    uint32_t u32CNR = 0, u32CMR = 0;
    
    u32CNR = PWM_GET_CNR(PWM0, id);
    if(u16PulseWidth >= MAX_PULSE_WIDTH)
        u32CMR = u32CNR+1;
    else if(u16PulseWidth == 0)
        u32CMR = 0;
    else
        u32CMR = (float)u16PulseWidth*ESC_FREQ_UPDATE_FREQ_DIV_1000000* u32CNR;    /* Duty cycle(%)= ratio*ESC_UPDATE_FREQ/1000000 */

    PWM_SET_CMR(PWM0, id, u32CMR);
    
	//PWM_ConfigOutputChannelf(PWM0, id, ESC_UPDATE_FREQ, (float)ratio*ESC_UPDATE_FREQ/10000);/*ratio*100*490/1000000*/
#else
	uint8_t u8Timer;

	switch(id) {
		case MOTOR_M1:
			u8Timer = DRVPWM_TIMER0;
			break;
		case MOTOR_M2:
			u8Timer = DRVPWM_TIMER1;
			break;
		case MOTOR_M3:
			u8Timer = DRVPWM_TIMER2;
			break;
		case MOTOR_M4:
			u8Timer = DRVPWM_TIMER3;
			break;
		default :
		u8Timer = 0;
	}

	sPt.u8HighPulseRatio = ratio;
	DrvPWM_SetTimerClk(u8Timer, &sPt);
#endif
} 
예제 #9
0
파일: main.c 프로젝트: brucetsao/Nuvoton
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
    /* Init System, IP clock and multi-function I/O
       In the end of SYS_Init() will issue SYS_LockReg()
       to lock protected register. If user want to write
       protected register, please issue SYS_UnlockReg()
       to unlock protected register if necessary */

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, IP clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART to 115200-8n1 for print message */
    UART0_Init();

    printf("\n\nCPU @ %dHz(PLL@ %dHz)\n", SystemCoreClock, PllClock);
    printf("PWM1 clock is from %s\n", (CLK->CLKSEL2 & CLK_CLKSEL2_PWM1SEL_Msk) ? "CPU" : "PLL");
    printf("+------------------------------------------------------------------------+\n");
    printf("|                          PWM Driver Sample Code                        |\n");
    printf("|                                                                        |\n");
    printf("+------------------------------------------------------------------------+\n");
    printf("  This sample code will use PWM1 channel 2 to capture the signal from PWM1 channel 0.\n");
    printf("  And the captured data is transferred by PDMA channel 0.\n");
    printf("  I/O configuration:\n");
    printf("    PWM1 channel 2(PC.11) <--> PWM1 channel 0(PC.6)\n\n");
    printf("Use PWM1 Channel 2(PC.11) to capture the PWM1 Channel 0(PC.6) Waveform\n");

    while(1)
    {
        printf("\n\nPress any key to start PWM Capture Test\n");
        getchar();

        /*--------------------------------------------------------------------------------------*/
        /* Set the PWM1 Channel 0 as PWM output function.                                       */
        /*--------------------------------------------------------------------------------------*/

        /* Assume PWM output frequency is 1500Hz and duty ratio is 30%, user can calculate PWM settings by follows.
           duty ratio = (CMR+1)/(CNR+1)
           cycle time = CNR+1
           High level = CMR+1
           PWM clock source frequency = PLL = 72000000
           (CNR+1) = PWM clock source frequency/prescaler/PWM output frequency
                   = 72000000/2/1500 = 24000
           (Note: CNR is 16 bits, so if calculated value is larger than 65536, user should increase prescale value.)
           CNR = 23999
           duty ratio = 30% ==> (CMR+1)/(CNR+1) = 30%
           CMR = 7199
           Prescale value is 1 : prescaler= 2
        */

        /*Set counter as down count*/
        PWM1->CTL1 = (PWM1->CTL1 & ~PWM_CTL1_CNTTYPE0_Msk) | 0x1;

        /*Set PWM Timer clock prescaler*/
        PWM_SET_PRESCALER(PWM1, 0, 1); // Divided by 2

        /*Set PWM Timer duty*/
        PWM_SET_CMR(PWM1, 0, 7199);

        /*Set PWM Timer period*/
        PWM_SET_CNR(PWM1, 0, 23999);

        /* Set waveform generation */
        PWM1->WGCTL0 = 0x00010000;
        PWM1->WGCTL1 = 0x00020000;

        /* Enable PWM Output path for PWM1 channel 0 */
        PWM1->POEN |= PWM_CH_0_MASK;

        /* Enable Timer for PWM1 channel 0 */
        PWM1->CNTEN |= PWM_CH_0_MASK;

        /*--------------------------------------------------------------------------------------*/
        /* Configure PDMA peripheral mode form PWM to memory                                    */
        /*--------------------------------------------------------------------------------------*/
        /* Open Channel 0 */
        PDMA->CHCTL |= 0x1;
        PDMA->DSCT[0].CTL &= ~(PDMA_DSCT_CTL_TXCNT_Msk | PDMA_DSCT_CTL_TXWIDTH_Msk);

        /* transfer width is half word(16 bit) and transfer count is 4 */
        PDMA->DSCT[0].CTL |= ((0x1 << PDMA_DSCT_CTL_TXWIDTH_Pos) | ((4 - 1) << PDMA_DSCT_CTL_TXCNT_Pos));

        /* Set source address as PWM capture channel PDMA register(no increment) and destination address as g_u32Count array(increment) */
        PDMA->DSCT[0].SA = (uint32_t)&PWM1->PDMACAP2_3;
        PDMA->DSCT[0].DA = (uint32_t)&g_u32Count[0];
        PDMA->DSCT[0].CTL &= ~(PDMA_DSCT_CTL_SAINC_Msk | PDMA_DSCT_CTL_DAINC_Msk);
        PDMA->DSCT[0].CTL |= ((0x3 << PDMA_DSCT_CTL_SAINC_Pos) | (0x2 << PDMA_DSCT_CTL_DAINC_Pos));

        /* Select PDMA request source as PWM RX(PWM1 channel 2 should be PWM1 pair 2) */
        PDMA->REQSEL0_3 = (PDMA->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC0_Msk) | (0xF << PDMA_REQSEL0_3_REQSRC0_Pos);

        /* Select PDMA operation mode as basic mode */
        PDMA->DSCT[0].CTL = (PDMA->DSCT[0].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | 0x1;

        /* Set PDMA as single request type for PWM */
        PDMA->DSCT[0].CTL = (PDMA->DSCT[0].CTL & ~(PDMA_DSCT_CTL_TXTYPE_Msk)) | (0x1 << PDMA_DSCT_CTL_TXTYPE_Pos);
        
        PDMA->INTEN |= (1 << 0);
        NVIC_EnableIRQ(PDMA_IRQn);

        /* Enable PDMA for PWM1 channel 2 capture function, and set capture order as falling first */
        PWM1->PDMACTL &= ~(PWM_PDMACTL_CHSEL2_3_Msk | PWM_PDMACTL_CAPORD2_3_Msk);
        
        /* Select capture mode as both rising and falling to do PDMA transfer */
        PWM1->PDMACTL |= (PWM_PDMACTL_CAPMOD2_3_Msk | PWM_PDMACTL_CHEN2_3_Msk);

        /*--------------------------------------------------------------------------------------*/
        /* Set the PWM1 channel 2 for capture function                                          */
        /*--------------------------------------------------------------------------------------*/

        /* If input minimum frequency is 1500Hz, user can calculate capture settings by follows.
           Capture clock source frequency = PLL = 72000000 in the sample code.
           (CNR+1) = Capture clock source frequency/prescaler/minimum input frequency
                   = 72000000/2/1500 = 24000
           (Note: CNR is 16 bits, so if calculated value is larger than 65536, user should increase prescale value.)
           CNR = 0xFFFF
           (Note: In capture mode, user should set CNR to 0xFFFF to increase capture frequency range.)
        */

        /*Set counter as down count*/
        PWM1->CTL1 = (PWM1->CTL1 & ~PWM_CTL1_CNTTYPE2_Msk) | (0x1 << PWM_CTL1_CNTTYPE2_Pos);

        /*Set PWM1 channel 2 Timer clock prescaler*/
        PWM_SET_PRESCALER(PWM1, 2, 1); // Divided by 2

        /*Set PWM1 channel 2 Timer period*/
        PWM_SET_CNR(PWM1, 2, 0xFFFF);

        /* Enable capture function */
        PWM1->CAPCTL |= PWM_CAPCTL_CAPEN2_Msk;

        /* Enable falling capture reload */
        PWM1->CAPCTL |= PWM_CAPCTL_FCRLDEN2_Msk;

        // Start
        PWM1->CNTEN |= PWM_CNTEN_CNTEN2_Msk;

        /* Wait until PWM1 channel 2 Timer start to count */
        while((PWM1->CNT[2]) == 0);

        /* Enable capture input path for PWM1 channel 2 */
        PWM1->CAPINEN |= PWM_CAPINEN_CAPINEN2_Msk;

        /* Capture the Input Waveform Data */
        //CalPeriodTime(PWM1, 2);
        CalPeriodTime();
        /*---------------------------------------------------------------------------------------------------------*/
        /* Stop PWM1 channel 0 (Recommended procedure method 1)                                                    */
        /* Set PWM Timer loaded value(Period) as 0. When PWM internal counter(CNT) reaches to 0, disable PWM Timer */
        /*---------------------------------------------------------------------------------------------------------*/

        /* Set PWM1 channel 0 loaded value as 0 */
        PWM1->PERIOD[0] = 0;

        /* Wait until PWM1 channel 0 Timer Stop */
        while((PWM1->CNT[0] & PWM_CNT_CNT_Msk) != 0);

        /* Disable Timer for PWM1 channel 0 */
        PWM1->CNTEN &= ~PWM_CNTEN_CNTEN0_Msk;

        /* Disable PWM Output path for PWM1 channel 0 */
        PWM1->POEN &= ~PWM_CH_0_MASK;

        /*---------------------------------------------------------------------------------------------------------*/
        /* Stop PWM1 channel 2 (Recommended procedure method 1)                                                    */
        /* Set PWM Timer loaded value(Period) as 0. When PWM internal counter(CNT) reaches to 0, disable PWM Timer */
        /*---------------------------------------------------------------------------------------------------------*/

        /* Disable PDMA NVIC */
        NVIC_DisableIRQ(PDMA_IRQn);

        /* Set loaded value as 0 for PWM1 channel 2 */
        PWM1->PERIOD[2] = 0;

        /* Wait until PWM1 channel 2 current counter reach to 0 */
        while((PWM1->CNT[2] & PWM_CNT_CNT_Msk) != 0);

        /* Disable Timer for PWM1 channel 2 */
        PWM1->CNTEN &= ~PWM_CNTEN_CNTEN2_Msk;

        /* Disable Capture Function and Capture Input path for  PWM1 channel 2*/
        PWM1->CAPCTL &= ~PWM_CAPCTL_CAPEN2_Msk;
        PWM1->CAPINEN &= ~PWM_CAPINEN_CAPINEN2_Msk;

        /* Clear Capture Interrupt flag for PWM1 channel 2 */
        PWM1->CAPIF = PWM_CAPIF_CFLIF2_Msk;

        PDMA->CHCTL = 0;
    }
}
예제 #10
0
int32_t main (void)
{
    /* Init System, IP clock and multi-function I/O
       In the end of SYS_Init() will issue SYS_LockReg()
       to lock protected register. If user want to write
       protected register, please issue SYS_UnlockReg()
       to unlock protected register if necessary */
    SYS_Init();

    /* Init UART to 115200-8n1 for print message */
    UART_Open(UART0, 115200);

    printf("\nThis sample code will output PWM channel 0 to with different duty\n");
    printf(", and enable/disable Precise Center Align function.\n");
    printf("Polling 1 period interrupt flag to get PWM channel 0 output.\n");

    // PWM-Timer 0 enable and Auto-reload
    PWM->CTL = PWM_CTL_CNTEN0_Msk | PWM_CTL_CNTMODE0_Msk;
    PWM_SET_PRESCALER(PWM, 0, 1);
    PWM_SET_DIVIDER(PWM, 0, PWM_CLK_DIV_1);

    // Set the PWM aligned type
    PWM_SET_ALIGNED_TYPE(PWM, 0, PWM_CENTER_ALIGNED);

    // Enable PWM channel 0 output
    PWM_EnableOutput(PWM, BIT0);

    // Start
    PWM_Start(PWM, BIT0);

    /*
    Precise Center Align and Center Align PWM channel 0 waveform of this sample shown below:

    |<- CNR-(2*(CMR+1))  ->|  CNR-(2*(CMR+1) = 401 -(2*(100+1)) CLKs
               |<-  CNR -( 2 *( CMR + 1))   ->|  CNR-(2*(CMR+1) = 402 -(2*(99+1)) CLKs
                                     |<-  2 *(CNR-CMR) clk ->|  2 * (CNR - CMR) = 2 * (401-100) CLKs
                                                       |<- 2 * (CNR-CMR) clk  ->|   2 * (CNR - CMR) = 2 * (402-99) CLKs
       ________          ____________          ________       ____________       ________          ____________          ________       ____________
    ____| 7.96us |_8.08us_|   24.08us  |_8.08us_| 8.08us |_8us_|   24.24us  |_8us_| 7.96us |_8.08us_|   24.08us  |_8.08us_| 8.08us |_8us_|   24.24us  |_8us_

    */

    while(1)
    {
        // Enable PWM Precise Center Aligned Type
        PWM->PCACTL = PWM_PCACTL_PCAEN_Msk;

        // PWM Channel 0 Output : duty = 7.96u, low = 8.08u
        PWM_SET_CMR(PWM, 0, 100);
        PWM_SET_CNR(PWM, 0, 401);

        // Polling, Wait 1 period interrupt flags
        while(PWM_GetPeriodIntFlag(PWM, 0) == 0);
        PWM_ClearPeriodIntFlag(PWM, 0);

        // Disable PWM Precise Center Aligned Type
        PWM->PCACTL &= ~(PWM_PCACTL_PCAEN_Msk);

        // PWM Channel 0 Output : duty = 24.08u, low = 8.08u
        PWM_SET_CMR(PWM, 0, 100);
        PWM_SET_CNR(PWM, 0, 401);

        // Polling, Wait 1 period interrupt flags
        while(PWM_GetPeriodIntFlag(PWM, 0) == 0);
        PWM_ClearPeriodIntFlag(PWM, 0);

        // Enable PWM Precise Center Aligned Type
        PWM->PCACTL = PWM_PCACTL_PCAEN_Msk;

        // PWM Channel 0 Output : duty = 8.08u, low = 8u
        PWM_SET_CMR(PWM, 0, 99);
        PWM_SET_CNR(PWM, 0, 402);

        // Polling, Wait 1 period interrupt flags
        while(PWM_GetPeriodIntFlag(PWM, 0) == 0);
        PWM_ClearPeriodIntFlag(PWM, 0);

        // Disable PWM Precise Center Aligned Type
        PWM->PCACTL &= ~(PWM_PCACTL_PCAEN_Msk);

        // PWM Channel 0 Output : duty = 24.24u, low = 8u
        PWM_SET_CMR(PWM, 0, 99);
        PWM_SET_CNR(PWM, 0, 402);

        // Polling, Wait 1 period interrupt flags
        while(PWM_GetPeriodIntFlag(PWM, 0) == 0);
        PWM_ClearPeriodIntFlag(PWM, 0);
    }

}