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); }
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); }
/** * 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); }
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; }
/** * @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); }
//========================================================================= //----- (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; } } }
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); } }
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 }
/*---------------------------------------------------------------------------------------------------------*/ 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; } }
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); } }