void open_pwm3(void) { SYS_UnlockReg(); SYS->P2_MFP |= SYS_MFP_P23_PWM3; SYS_LockReg(); /*Set Pwm mode*/ _PWM_SET_TIMER_AUTO_RELOAD_MODE(PWMA,PWM_CH3); /*Set PWM Timer clock prescaler*/ _PWM_SET_TIMER_PRESCALE(PWMA,PWM_CH3,2); // Divided by 2 /*Set PWM Timer clock divider select*/ _PWM_SET_TIMER_CLOCK_DIV(PWMA,PWM_CH3,PWM_CSR_DIV16); PWMA->CMR3 = Brightness[19]; /*Set PWM Timer period*/ PWMA->CNR3 = 0xffff; /* Enable PWM Output pin */ _PWM_ENABLE_PWM_OUT(PWMA,PWM_CH3); /* Enable Timer period Interrupt */ _PWM_ENABLE_TIMER_PERIOD_INT(PWMA,PWM_CH3); /* Enable PWMB NVIC */ NVIC_EnableIRQ((IRQn_Type)(PWMA_IRQn)); /* Enable PWM Timer */ _PWM_ENABLE_TIMER(PWMA,PWM_CH3); }
void EXPWM_Init(expwmtype *data) { PWM_T *PWM_MODULE = (PWM_T *)(data->Chanell < 4 ? PWMA : PWMB); unsigned char Chanell = data->Chanell; if(Chanell > 3) { Chanell -= 4; } if((data->Chanell == 0 || data->Chanell == 1) && !_expwm_pwm01_isinit) { SYSCLK->APBCLK |= SYSCLK_APBCLK_PWM01_EN_Msk; SYSCLK->CLKSEL1 &= ~SYSCLK_CLKSEL1_PWM01_S_Msk; SYSCLK->CLKSEL1 |= SYSCLK_CLKSEL1_PWM01_HCLK; _expwm_pwm01_isinit = 1; } if((data->Chanell == 2 || data->Chanell == 3) && !_expwm_pwm23_isinit) { SYSCLK->APBCLK |= SYSCLK_APBCLK_PWM23_EN_Msk; SYSCLK->CLKSEL1 &= ~SYSCLK_CLKSEL1_PWM23_S_Msk; SYSCLK->CLKSEL1 |= SYSCLK_CLKSEL1_PWM23_HCLK; _expwm_pwm23_isinit = 1; } if((data->Chanell == 4 || data->Chanell == 5) && !_expwm_pwm45_isinit) { SYSCLK->APBCLK |= SYSCLK_APBCLK_PWM45_EN_Msk; SYSCLK->CLKSEL2 &= ~SYSCLK_CLKSEL2_PWM45_S_Msk; SYSCLK->CLKSEL2 |= SYSCLK_CLKSEL2_PWM45_HCLK; _expwm_pwm45_isinit = 1; } if((data->Chanell == 6 || data->Chanell == 7) && !_expwm_pwm67_isinit) { SYSCLK->APBCLK |= SYSCLK_APBCLK_PWM67_EN_Msk; SYSCLK->CLKSEL2 &= ~SYSCLK_CLKSEL2_PWM67_S_Msk; SYSCLK->CLKSEL2 |= SYSCLK_CLKSEL2_PWM67_HCLK; _expwm_pwm67_isinit = 1; } if(data->Chanell < 4) { // Initialize module a interrupt if(!_expwm_pwma_isinit) { NVIC_EnableIRQ(PWMA_IRQn); _expwm_pwma_isinit = 1; } } else { // Initialize module b interrupt if(!_expwm_pwmb_isinit) { NVIC_EnableIRQ(PWMB_IRQn); _expwm_pwmb_isinit = 1; } } _PWM_SET_TIMER_AUTO_RELOAD_MODE(PWM_MODULE,Chanell); _PWM_SET_TIMER_PRESCALE(PWM_MODULE,Chanell, data->Prescaler); _PWM_SET_TIMER_CLOCK_DIV(PWM_MODULE,Chanell,data->Divider); _PWM_SET_PWM_COMP_VALUE(PWM_MODULE,Chanell,data->Duty); _PWM_SET_TIMER_LOADED_VALUE(PWM_MODULE,Chanell,data->Period); _PWM_ENABLE_PWM_OUT(PWM_MODULE,Chanell); switch(data->Port) { case EXPWM_PORT2: SYS->P2_MFP |= 0x1UL << (data->Chanell + 8); break; case EXPWM_PORT4: SYS->P4_MFP |= 0x1UL << data->Chanell; break; default: break; } if(data->Callback != 0) { _PWM_ENABLE_TIMER_PERIOD_INT(PWM_MODULE, Chanell); _expwm_callback_arr[data->Chanell] = data->Callback; } _PWM_ENABLE_TIMER(PWM_MODULE, Chanell); }
void open_pwm(char channel) { /* Assume PWM output frequency is 523Hz and duty ratio is 60%, 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 = __XTAL = 12000000 (CNR+1) = PWM clock source frequency/prescaler/clock source divider/PWM output frequency = 12000000/2/1/523 = 11472 (Note: CNR is 16 bits, so if calculated value is larger than 65536, user should increase prescale value.) CNR = 11471 duty ratio = 60% ==> (CMR+1)/(CNR+1) = 60% ==> CMR = (CNR+1)*0.6-1 = 11472*60/100-1 CMR = 6882 Prescale value is 1 : prescaler= 2 Clock divider is PWM_CSR_DIV1 : clock divider =1 */ char pwm_channel; if(channel==0) { pwm_channel=PWM_CH0; SYS_UnlockReg(); SYS->P2_MFP |= SYS_MFP_P20_PWM0; SYS_LockReg(); } else { pwm_channel=PWM_CH1; SYS_UnlockReg(); SYS->P2_MFP |= SYS_MFP_P21_PWM1; SYS_LockReg(); } /*Set Pwm mode*/ _PWM_SET_TIMER_AUTO_RELOAD_MODE(PWMA,pwm_channel); /*Set PWM Timer clock prescaler*/ _PWM_SET_TIMER_PRESCALE(PWMA,pwm_channel,1); // Divided by 2 /*Set PWM Timer clock divider select*/ _PWM_SET_TIMER_CLOCK_DIV(PWMA,pwm_channel,PWM_CSR_DIV1); if(pwm_channel==PWM_CH0) { /*Set PWM Timer duty*/ //PWMA->CMR0 = g_au16ScaleCmr[0]; PWMA->CMR0 = 0; /*Set PWM Timer period*/ PWMA->CNR0 = 0xffff; } else { /*Set PWM Timer duty*/ PWMA->CMR1 = 0; //PWMA->CMR1 = Brightness[19]; /*Set PWM Timer period*/ PWMA->CNR1 = 0xffff; } /* Enable PWM Output pin */ _PWM_ENABLE_PWM_OUT(PWMA,pwm_channel); /* Enable Timer period Interrupt */ _PWM_ENABLE_TIMER_PERIOD_INT(PWMA,pwm_channel); /* Enable PWMB NVIC */ NVIC_EnableIRQ((IRQn_Type)(PWMA_IRQn)); /* Enable PWM Timer */ _PWM_ENABLE_TIMER(PWMA,pwm_channel); }
/*---------------------------------------------------------------------------------------------------------*/ int32_t main (void) { uint8_t u8Item; int32_t i32Loop = 1; int32_t i32TestLoop = 1; /* Init System, IP clock and multi-function I/O */ SYS_Init(); //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. /* Init UART0 for printf */ UART0_Init(); printf("+------------------------------------------------------------------------+\n"); printf("| PWM Driver Sample Code |\n"); printf("| |\n"); printf("+------------------------------------------------------------------------+\n"); printf(" This sample code will use PWMB channel 0 to drive Buzzer or use PWMB channel 2 to capture\n the signal from PWMB channel 1.\n"); printf(" I/O configuration:\n"); printf(" PWM4(P2.4 PWMB channel 0) <--> Buzzer\n"); printf(" PWM5(P2.5 PWMB channel 1) <--> PWM6(P2.6 PWMB channel 2)\n\n"); while (i32Loop) { printf("\n Please Select Test Item\n"); printf(" 0 : Exit\n"); printf(" 1 : PWM Timer Waveform Test.\n"); printf(" 2 : PWM Caputre Test\n"); u8Item = getchar(); switch (u8Item) { case '0': { i32Loop = 0; break; } case '1': { uint8_t u8ItemOK; printf("\nPWM Timer Waveform Test. Waveform output(P2.4 PWMB channel 0) to Buzzer\n"); /* P2.4 PWMB channel 0 generates PWM frequency Do - Si */ i32TestLoop = 1; printf("Select Test Item\n"); printf(" 1: Do (523Hz)Tenor C\n"); printf(" 2: Re (587Hz)\n"); printf(" 3: Mi (659Hz)\n"); printf(" 4: Fa (698Hz)\n"); printf(" 5: Sol(784Hz) \n"); printf(" 6: La (880Hz)\n"); printf(" 7: Si (988Hz)\n"); printf(" 0: Exit\n"); while (i32TestLoop) { u8ItemOK = 1; u8Item = getchar(); switch (u8Item) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': g_u16Frequency = g_au16ScaleFreq[(u8Item-'1')]; break; case '0': i32TestLoop = 0; break; default: u8ItemOK = 0; break; } if (i32TestLoop && u8ItemOK) { g_u32Pulse = 0; g_u8PWMCount = 1; /* Assume PWM output frequency is 523Hz and duty ratio is 60%, 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 = __XTAL = 12000000 (CNR+1) = PWM clock source frequency/prescaler/clock source divider/PWM output frequency = 12000000/2/1/523 = 11472 (Note: CNR is 16 bits, so if calculated value is larger than 65536, user should increase prescale value.) CNR = 11471 duty ratio = 60% ==> (CMR+1)/(CNR+1) = 60% ==> CMR = (CNR+1)*0.6-1 = 11472*60/100-1 CMR = 6882 Prescale value is 1 : prescaler= 2 Clock divider is PWM_CSR_DIV1 : clock divider =1 */ /*Set Pwm mode*/ _PWM_SET_TIMER_AUTO_RELOAD_MODE(PWMB,PWM_CH0); /*Set PWM Timer clock prescaler*/ _PWM_SET_TIMER_PRESCALE(PWMB,PWM_CH0, 1); // Divided by 2 /*Set PWM Timer clock divider select*/ _PWM_SET_TIMER_CLOCK_DIV(PWMB,PWM_CH0,PWM_CSR_DIV1); /*Set PWM Timer duty*/ PWMB->CMR0 = g_au16ScaleCmr[(u8Item-'1')]; /*Set PWM Timer period*/ PWMB->CNR0 = g_au16ScaleCnr[(u8Item-'1')]; /* Enable PWM Output pin */ _PWM_ENABLE_PWM_OUT(PWMB, PWM_CH0); /* Enable Timer period Interrupt */ _PWM_ENABLE_TIMER_PERIOD_INT(PWMB, PWM_CH0); /* Enable PWMB NVIC */ NVIC_EnableIRQ((IRQn_Type)(PWMB_IRQn)); /* Enable PWM Timer */ _PWM_ENABLE_TIMER(PWMB, PWM_CH0); while (g_u8PWMCount); /*--------------------------------------------------------------------------------------*/ /* Stop PWM Timer (Recommended procedure method 2) */ /* Set PWM Timer counter as 0, When interrupt request happen, disable PWM Timer */ /* Set PWM Timer counter as 0 in Call back function */ /*--------------------------------------------------------------------------------------*/ /* Disable PWMB NVIC */ NVIC_DisableIRQ((IRQn_Type)(PWMB_IRQn)); /* Wait until PWMB channel 0 Timer Stop */ while(PWMB->PDR0!=0); /* Disable the PWM Timer */ _PWM_DISABLE_TIMER(PWMB, PWM_CH0); /* Disable PWM Output pin */ _PWM_DISABLE_PWM_OUT(PWMB, PWM_CH0); } } break; } case '2': { printf("PWM Capture Test\n"); printf("Use PWMB Channel 2(P2.6) to capture the PWMB Channel 1(P2.5) Waveform\n"); /*--------------------------------------------------------------------------------------*/ /* Set the PWMB Channel 1 as PWM output function. */ /*--------------------------------------------------------------------------------------*/ /* Assume PWM output frequency is 250Hz 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 = __XTAL = 12000000 (CNR+1) = PWM clock source frequency/prescaler/clock source divider/PWM output frequency = 12000000/2/1/250 = 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 Clock divider is PWM_CSR_DIV1 : clock divider =1 */ /*Set Pwm mode*/ _PWM_SET_TIMER_AUTO_RELOAD_MODE(PWMB,PWM_CH1); /*Set PWM Timer clock prescaler*/ _PWM_SET_TIMER_PRESCALE(PWMB,PWM_CH1, 1); // Divided by 2 /*Set PWM Timer clock divider select*/ _PWM_SET_TIMER_CLOCK_DIV(PWMB,PWM_CH1,PWM_CSR_DIV1); /*Set PWM Timer duty*/ PWMB->CMR1 = 7199; /*Set PWM Timer period*/ PWMB->CNR1 = 23999; /* Enable PWM Output path for PWMB channel 1 */ _PWM_ENABLE_PWM_OUT(PWMB, PWM_CH1); /* Enable Timer for PWMB channel 1 */ _PWM_ENABLE_TIMER(PWMB, PWM_CH1); /*--------------------------------------------------------------------------------------*/ /* Set the PWMB channel 2 for capture function */ /*--------------------------------------------------------------------------------------*/ /* If input minimum frequency is 250Hz, user can calculate capture settings by follows. Capture clock source frequency = __XTAL = 12000000 in the sample code. (CNR+1) = Capture clock source frequency/prescaler/clock source divider/minimum input frequency = 12000000/2/1/250 = 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 Pwm mode*/ _PWM_SET_TIMER_AUTO_RELOAD_MODE(PWMB,PWM_CH2); /*Set PWM Timer clock prescaler*/ _PWM_SET_TIMER_PRESCALE(PWMB,PWM_CH2, 1); // Divided by 2 /*Set PWM Timer clock divider select*/ _PWM_SET_TIMER_CLOCK_DIV(PWMB,PWM_CH2,PWM_CSR_DIV1); /*Set PWM Timer loaded value*/ PWMB->CNR2 = 0xFFFF; /* Enable capture falling edge interrupt for PWMB channel 2 */ _PWM_ENABLE_CAP_FALLING_INT(PWMB, PWM_CH2); /* Enable PWMB NVIC interrupt */ NVIC_EnableIRQ((IRQn_Type)(PWMB_IRQn)); /* Enable Capture Function for PWMB channel 2 */ _PWM_ENABLE_CAP_FUNC(PWMB, PWM_CH2); /* Enable Timer for PWMB channel 2 */ _PWM_ENABLE_TIMER(PWMB, PWM_CH2); /* Wait until PWMB channel 2 Timer start to count */ while(PWMB->PDR2==0); /* Enable capture input path for PWMB channel 2 */ _PWM_ENABLE_CAP_IN(PWMB, PWM_CH2); /* Capture the Input Waveform Data */ CalPeriodTime(PWMB, PWM_CH2); /*------------------------------------------------------------------------------------------------------*/ /* Stop PWMB channel 1 (Recommended procedure method 1) */ /* Set PWM Timer loaded value(CNR) as 0. When PWM internal counter(PDR) reaches to 0, disable PWM Timer */ /*------------------------------------------------------------------------------------------------------*/ /* Set PWMB channel 1 loaded value as 0 */ PWMB->CNR1 =0; /* Wait until PWMB channel 1 Timer Stop */ while(PWMB->PDR1!=0); /* Disable Timer for PWMB channel 1 */ _PWM_DISABLE_TIMER(PWMB, PWM_CH1); /* Disable PWM Output path for PWMB channel 1 */ _PWM_DISABLE_PWM_OUT(PWMB, PWM_CH1); /*------------------------------------------------------------------------------------------------------*/ /* Stop PWMB channel 2 (Recommended procedure method 1) */ /* Set PWM Timer loaded value(CNR) as 0. When PWM internal counter(PDR) reaches to 0, disable PWM Timer */ /*------------------------------------------------------------------------------------------------------*/ /* Disable PWMB NVIC */ NVIC_DisableIRQ((IRQn_Type)(PWMB_IRQn)); /* Set loaded value as 0 for PWMB channel 2 */ PWMB->CNR2 =0; /* Wait until PWMB channel 2 current counter reach to 0 */ while(PWMB->PDR2!=0); /* Disable Timer for PWMB channel 2 */ _PWM_DISABLE_TIMER(PWMB, PWM_CH2); /* Disable Capture Function for PWMB channel 2*/ _PWM_DISABLE_CAP_FUNC(PWMB, PWM_CH2); /* Clear Capture Interrupt flag for PWMB channel 2*/ _PWM_CLR_CAP_INT_FLAG(PWMB, PWM_CH2); /* Disable Capture Input path for PWMB channel 2 */ _PWM_DISABLE_CAP_IN(PWMB, PWM_CH2); break; } } } printf("PWM sample is complete.\n"); /* Disable PWMB clock engine */ SYSCLK->APBCLK&=(~(SYSCLK_APBCLK_PWM45_EN_Msk|SYSCLK_APBCLK_PWM67_EN_Msk)); return 0; }