void Pwm_SetDutyCycle(Pwm_ChannelType enChannelNumber, uint16_t DutyCycle) { if(DutyCycle < FTM_Period) { switch(enChannelNumber) { case CHANNEL0:{ FTM3_SC = 0; /* Make sure its Off! */ FTM3_C0V = DutyCycle; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case CHANNEL1:{ FTM3_SC = 0; /* Make sure its Off! */ FTM3_C1V = DutyCycle; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case CHANNEL2:{ FTM3_SC = 0; /* Make sure its Off! */ FTM3_C2V = DutyCycle; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case CHANNEL3:{ FTM3_SC = 0; /* Make sure its Off! */ FTM3_C3V = DutyCycle; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case CHANNEL4:{}break; case CHANNEL5:{}break; case CHANNEL6:{ FTM3_SC = 0; /* Make sure its Off! */ FTM3_C6V = DutyCycle; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case CHANNEL7:{}break; } } }
void Pwm_DeInit(void) { SIM_SCGC3 = 0; /* Enable clock for FTM3 */ /*FTM0_MODE[WPDIS] = 1; Disable Write Protection - enables changes to QUADEN, DECAPEN */ FTM3_MODE = 0; /* FTMEN is bit 0, need to set to zero so DECAPEN can be set to 0 */ FTM3_MODE = 0; /* QUADEN is Bit 1, Set Quadrature Decoder Mode (QUADEN) Enable to 0, (disabled)*/ FTM3_QDCTRL &=~0; FTM3_CNT = 0x0; /* FTM Counter Value - reset counter to zero */ FTM3_MOD = 0; /* Set Fixed Period 0x1D3 -> 1KHz*/ FTM3_CNTIN = 0; /* Set the Counter Initial Value to 0 */ /* Edit registers when no clock is fed to timer so the MOD value, gets pushed in immediately */ FTM3_SC = 0; /* Make sure its Off! */ FTM3_C0V = 0; FTM3_C1V = 0; FTM3_C2V = 0; FTM3_C3V = 0; FTM3_C6V = 0; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }
/* * LPLD_FTM_PWM_Init * FTM模块PWM模式初始化,内部调用 */ static uint8 LPLD_FTM_PWM_Init(FTM_InitTypeDef ftm_init_structure) { uint32 bus_clk_hz; uint32 mod, mod2; uint8 ps; uint32 freq = ftm_init_structure.FTM_PwmFreq; uint32 dt_en = ftm_init_structure.FTM_PwmDeadtimeCfg; uint8 dt_div = ftm_init_structure.FTM_PwmDeadtimeDiv; uint8 dt_val = ftm_init_structure.FTM_PwmDeadtimeVal; FTM_MemMapPtr ftmx = ftm_init_structure.FTM_Ftmx; //参数检查 //ASSERT( freq ); //判断频率 //ASSERT( dt_val<=63 ); //判断死区插入值 if (dt_val > 63) return 0; bus_clk_hz = g_bus_clock; if(freq>bus_clk_hz) return 0; //这段代码写的比较有趣... if((mod=bus_clk_hz/(freq*128)) < 0xFFFFu) { ps = 7; mod2=mod; if((mod=bus_clk_hz/(freq*64)) < 0xFFFFu) { ps = 6; mod2=mod; if((mod=bus_clk_hz/(freq*32)) < 0xFFFFu) { ps = 5; mod2=mod; if((mod=bus_clk_hz/(freq*16)) < 0xFFFFu) { ps = 4; mod2=mod; if((mod=bus_clk_hz/(freq*8)) < 0xFFFFu) { ps = 3; mod2=mod; if((mod=bus_clk_hz/(freq*4)) < 0xFFFFu) { ps = 2; mod2=mod; if((mod=bus_clk_hz/(freq*2)) < 0xFFFFu) { ps = 1; mod2=mod; if((mod=bus_clk_hz/(freq*1)) < 0xFFFFu) { ps = 0; mod2=mod; } } } } } } } } else { return 0; } ftmx->SC = 0; // 设置PWM周期及占空比 // PWM周期 = (MOD-CNTIN+1)*FTM时钟周期 : // 配置FTM计数初始值 ftmx->CNT = 0; ftmx->CNTIN = 0; // 配置FTM计数MOD值 ftmx->MOD = mod2; ftmx->DEADTIME = FTM_DEADTIME_DTPS(dt_div) | FTM_DEADTIME_DTVAL(dt_val); ftmx->COMBINE = dt_en; //使能死区 // 配置FTM控制寄存器 // 禁用中断, 加计数模式, 时钟源:System clock(Bus Clk), 分频系数:8 // 假设SysClk = 50MHz, SC_PS=3, FTM Clk = 50MHz/2^3 = 6.25MHz ftmx->SC = FTM_SC_CLKS(1)|FTM_SC_PS(ps); return 1; }
status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) { assert(config); uint32_t reg; if (!(config->pwmSyncMode & (FTM_SYNC_TRIG0_MASK | FTM_SYNC_TRIG1_MASK | FTM_SYNC_TRIG2_MASK | FTM_SYNC_SWSYNC_MASK))) { /* Invalid PWM sync mode */ return kStatus_Fail; } /* Ungate the FTM clock*/ CLOCK_EnableClock(s_ftmClocks[FTM_GetInstance(base)]); /* Configure the fault mode, enable FTM mode and disable write protection */ base->MODE = FTM_MODE_FAULTM(config->faultMode) | FTM_MODE_FTMEN_MASK | FTM_MODE_WPDIS_MASK; /* Configure the update mechanism for buffered registers */ FTM_SetPwmSync(base, config->pwmSyncMode); if (config->reloadPoints) { /* Setup intermediate register reload points */ FTM_SetReloadPoints(base, config->reloadPoints); } /* Set the clock prescale factor */ base->SC = FTM_SC_PS(config->prescale); /* Setup the counter operation */ base->CONF = (FTM_CONF_BDMMODE(config->bdmMode) | FTM_CONF_GTBEEN(config->useGlobalTimeBase)); /* Initial state of channel output */ base->OUTINIT = config->chnlInitState; /* Channel polarity */ base->POL = config->chnlPolarity; /* Set the external trigger sources */ base->EXTTRIG = config->extTriggers; #if defined(FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER) && (FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER) if (config->extTriggers & kFTM_ReloadInitTrigger) { base->CONF |= FTM_CONF_ITRIGR_MASK; } else { base->CONF &= ~FTM_CONF_ITRIGR_MASK; } #endif /* FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER */ /* FTM deadtime insertion control */ base->DEADTIME = (FTM_DEADTIME_DTPS(config->deadTimePrescale) | FTM_DEADTIME_DTVAL(config->deadTimeValue)); /* FTM fault filter value */ reg = base->FLTCTRL; reg &= ~FTM_FLTCTRL_FFVAL_MASK; reg |= FTM_FLTCTRL_FFVAL(config->faultFilterValue); base->FLTCTRL = reg; return kStatus_Success; }
/************************************************************************* * Function Name: FTM0_init * Parameters: none * Return: none * Description: FlexTimer 0 initialization *************************************************************************/ void FTM0_init(void) { FTM_HAL_SetWriteProtectionCmd(FTM0_BASE_PTR, false);//false: Write-protection is disabled FTM_HAL_Enable(FTM0_BASE_PTR, true);//true: all registers including FTM-specific registers are available FTM_HAL_SetCounterInitVal(FTM0_BASE_PTR, (uint16_t)(-PWM_MODULO/2)); FTM_HAL_SetMod(FTM0_BASE_PTR, (uint16_t)PWM_MODULO/2-1); // 20 kHz FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 0, 2); FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 1, 2); FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 2, 2); FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 3, 2); FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 4, 2); FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 5, 2); // output mask updated on PWM synchronization (not on rising edge of clock) FTM_HAL_SetMaxLoadingCmd(FTM0_BASE_PTR, true);//True to enable minimum loading point FTM_HAL_SetOutmaskPwmSyncModeCmd(FTM0_BASE_PTR, 1);//true if OUTMASK register is updated only by PWM sync\n FTM_HAL_SetDualChnPwmSyncCmd(FTM0_BASE_PTR, 0, true);//True to enable PWM synchronization FTM_HAL_SetDualChnPwmSyncCmd(FTM0_BASE_PTR, 1, true); FTM_HAL_SetDualChnPwmSyncCmd(FTM0_BASE_PTR, 2, true); FTM_HAL_SetDualChnDeadtimeCmd(FTM0_BASE_PTR, 0, true);//True to enable deadtime insertion, false to disable FTM_HAL_SetDualChnDeadtimeCmd(FTM0_BASE_PTR, 1, true); FTM_HAL_SetDualChnDeadtimeCmd(FTM0_BASE_PTR, 2, true); FTM_HAL_SetDualChnCompCmd(FTM0_BASE_PTR, 0, true);//True to enable complementary mode, false to disable FTM_HAL_SetDualChnCompCmd(FTM0_BASE_PTR, 1, true); FTM_HAL_SetDualChnCompCmd(FTM0_BASE_PTR, 2, true); FTM_HAL_SetDualChnCombineCmd(FTM0_BASE_PTR, 0, true);// True to enable channel pair to combine, false to disable FTM_HAL_SetDualChnCombineCmd(FTM0_BASE_PTR, 1, true); FTM_HAL_SetDualChnCombineCmd(FTM0_BASE_PTR, 2, true); // High transistors have negative polarity (MC33927/37) FTM_HAL_SetDeadtimePrescale(FTM0_BASE_PTR, kFtmDivided1); FTM_HAL_SetDeadtimeCount(FTM0_BASE_PTR, FTM_DEADTIME_DTVAL(63)); // DTVAL - deadtime value (0-63): deadtime period = DTPS x DTVAL FTM_HAL_SetInitTriggerCmd(FTM0_BASE_PTR, true);//True to enable, false to disable FTM_HAL_SetChnOutputPolarityCmd(FTM0_BASE_PTR, 0, 1); FTM_HAL_SetChnOutputPolarityCmd(FTM0_BASE_PTR, 2, 1); FTM_HAL_SetChnOutputPolarityCmd(FTM0_BASE_PTR, 4, 1); /* Following line configures: - enhanced PWM synchronization, FTM counter reset on SW sync - output SW control / polarity registers updated on PWM synchronization (not on rising edge of clock) - output SW control/inverting(swap)/mask registers updated from buffers on SW synchronization */ FTM_HAL_SetPwmSyncModeCmd(FTM0_BASE_PTR, true);// true means use Enhanced PWM synchronization\n FTM_HAL_SetCounterSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software trigger activates register sync\n FTM_HAL_SetSwoctrlPwmSyncModeCmd(FTM0_BASE_PTR, true);//true means SWOCTRL register is updated by PWM synch\n FTM_HAL_SetInvctrlPwmSyncModeCmd(FTM0_BASE_PTR, true);//true means INVCTRL register is updated by PWM synch\n FTM_HAL_SetSwoctrlSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software trigger activates register sync\n FTM_HAL_SetInvctrlSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software trigger activates register sync\n FTM_HAL_SetOutmaskSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 0, 1);//Sets the FTM peripheral timer channel output mask. FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 1, 1); FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 2, 1); FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 3, 1); FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 4, 1); FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 5, 1); FTM_HAL_SetCounter(FTM0_BASE_PTR, 1U); // update of FTM settings // no ISR, counting up, system clock, divide by 1 FTM_HAL_SetClockSource(FTM0_BASE_PTR, kClock_source_FTM_SystemClk); FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 0, (uint16_t)(-PWM_MODULO/4)); FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 1,(uint16_t) PWM_MODULO/4); FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 2, (uint16_t)(-PWM_MODULO/4)); FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 3,(uint16_t) PWM_MODULO/4); FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 4, (uint16_t)(-PWM_MODULO/4)); FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 5,(uint16_t) PWM_MODULO/4); FTM_HAL_SetSoftwareTriggerCmd(FTM0_BASE_PTR, 1); FTM_HAL_SetPwmLoadCmd(FTM0_BASE_PTR, 1); // FTM0 PWM output pins PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 1, kPortMuxAlt4); PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 3, kPortMuxAlt4); PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 4, kPortMuxAlt4); PORT_HAL_SetMuxMode(PORTD_BASE_PTR, 4, kPortMuxAlt4); PORT_HAL_SetMuxMode(PORTD_BASE_PTR, 5, kPortMuxAlt4); #if defined(KV10Z7_SERIES) PORT_HAL_SetMuxMode(PORTE_BASE_PTR, 25, kPortMuxAlt3); #elif (defined(KV10Z1287_SERIES) || defined(KV11Z7_SERIES)) PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 2, kPortMuxAlt4); #endif GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 1, kGpioDigitalOutput); GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 3, kGpioDigitalOutput); GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 4, kGpioDigitalOutput); GPIO_HAL_SetPinDir(GPIOD_BASE_PTR, 4, kGpioDigitalOutput); GPIO_HAL_SetPinDir(GPIOD_BASE_PTR, 5, kGpioDigitalOutput); #if defined(KV10Z7_SERIES) GPIO_HAL_SetPinDir(GPIOE_BASE_PTR, 25, kGpioDigitalOutput); #elif (defined(KV10Z1287_SERIES) || defined(KV11Z7_SERIES)) GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 2, kGpioDigitalOutput); #endif }
void Pwm_Init(const Pwm_ConfigType* FtmConfig) { for(uint8_t i=0;i<(FtmConfig->u8NumOfChannel); i++) { switch(FtmConfig->pstPwm_Settings[i].enFlxTimerID) { case 0: {}break; case 1: {}break; case 2: {}break; case 3: { SIM_SCGC3 |= SIM_SCGC3_FTM3_MASK; /* Enable clock for FTM3 */ /*FTM0_MODE[WPDIS] = 1; Disable Write Protection - enables changes to QUADEN, DECAPEN */ FTM3_MODE |= FTM_MODE_WPDIS_MASK; /* FTMEN is bit 0, need to set to zero so DECAPEN can be set to 0 */ FTM3_MODE |= FTM_MODE_FTMEN_MASK; /* QUADEN is Bit 1, Set Quadrature Decoder Mode (QUADEN) Enable to 0, (disabled)*/ FTM3_QDCTRL &=~FTM_QDCTRL_QUADEN_MASK; FTM3_CNT = 0x0; /* FTM Counter Value - reset counter to zero */ FTM3_MOD = FTM_Period; /* Set Fixed Period 0x1D3 -> 1KHz*/ FTM3_CNTIN = 0; /* Set the Counter Initial Value to 0 */ /* Edit registers when no clock is fed to timer so the MOD value, gets pushed in immediately */ FTM3_SC = 0; /* Make sure its Off! */ switch(FtmConfig->pstPwm_Settings[i].enPwmChannel) { case 0: { PORTD_PCR0 = PORT_PCR_MUX(0x4); FTM3_C0SC = FtmConfig->pstPwm_Settings[i].u8PwmAlignIntCfg; FTM3_C0V = FtmConfig->pstPwm_Settings[i].u16PwmDuty; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case 1: { PORTD_PCR1 = PORT_PCR_MUX(0x4); FTM3_C1SC = FtmConfig->pstPwm_Settings[i].u8PwmAlignIntCfg; FTM3_C1V = FtmConfig->pstPwm_Settings[i].u16PwmDuty; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case 2: { PORTD_PCR2= PORT_PCR_MUX(0x4); FTM3_C2SC = FtmConfig->pstPwm_Settings[i].u8PwmAlignIntCfg; FTM3_C2V = FtmConfig->pstPwm_Settings[i].u16PwmDuty; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case 3: { PORTD_PCR3 = PORT_PCR_MUX(0x4); FTM3_C3SC = FtmConfig->pstPwm_Settings[i].u8PwmAlignIntCfg; FTM3_C3V = FtmConfig->pstPwm_Settings[i].u16PwmDuty; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; case 6: { PORTC_PCR10 = PORT_PCR_MUX(0x3); FTM3_C6SC = FtmConfig->pstPwm_Settings[i].u8PwmAlignIntCfg; FTM3_C6V = FtmConfig->pstPwm_Settings[i].u16PwmDuty; FTM3_COMBINE = 0x0; FTM3_DEADTIME = FTM_DEADTIME_DTVAL(50); /* About 5usec */ FTM3_SC = 0x08 | FTM_SC_PS(0x7); /* Edge Aligned PWM running from BUSCLK / 1 */ FTM3_PWMLOAD |= FTM_PWMLOAD_LDOK_MASK; }break; default: {}break; } }break; default:{}break; } } }