标签:
一、头文件:
#ifndef _FTM_H_ #define _FTM_H_ #include "common.h" extern volatile struct FTM_MemMap *FTMx[3]; typedef enum FTMn { FTM0, FTM1, FTM2 } FTMn; typedef enum CHn { // --FTM0-- --FTM1-- --FTM2-- CH0, // PTC1 PTA8 PTB18 CH1, // PTC2 PTA9 PTB19 CH2, // PTC3 × × CH3, // PTC4 × × CH4, // PTD4 × × CH5, // PTD5 × × CH6, // PTD6 × × CH7 // PTD7 × × // ×表示不存在 } CHn; /*********************** PWM **************************/ #define FTM0_PRECISON 3000u //定义占空比精度,100即精度为1%,1000u则精度为0.1%,用于占空比 duty 形参传入,即占空比为 duty/FTM_PRECISON #define FTM1_PRECISON 3000u #define FTM2_PRECISON 6000u void FTM_PWM_init(FTMn, CHn, u32 freq, u32 duty); //初始化FTM的PWM功能并设置频率、占空比。设置通道输出占空比。同一个FTM,各通道的PWM频率是一样的,共3个FTM void FTM_PWM_Duty(FTMn, CHn, u32 duty); //设置通道占空比,占空比为 (duty * 精度) % ,如果 FTM_PRECISON 定义为 1000 ,duty = 100 ,则占空比 100*0.1%=10% void FTM_PWM_freq(FTMn, u32 freq); 2//设置FTM的频率 /*********************** 输入捕捉 **************************/ typedef enum Input_cfg { Rising, //上升沿捕捉 Falling, //下降沿捕捉 Rising_or_Falling //跳变沿捕捉 } Input_cfg; void FTM_Input_init(FTMn, CHn, Input_cfg); #define FTM_IRQ_EN(FTMn,CHn) FTM_CnSC_REG(FTMx[FTMn],CHn) |= FTM_CnSC_CHIE_MASK //开启 FTMn_CHn 中断 #define FTM_IRQ_DIS(FTMn,CHn) FTM_CnSC_REG(FTMx[FTMn],CHn) &= ~FTM_CnSC_CHIE_MASK //关闭 FTMn_CHn 中断 void FTM2_QUAD_Int(void); void FTM1_QUAD_Int(void); #endif //_FTM_H_
二、源文件:
#include "common.h" #include "ftm.h" /*********** FTMn_CHn PWM输出初始化函数 ***********/ volatile struct FTM_MemMap *FTMx[3] = {FTM0_BASE_PTR, FTM1_BASE_PTR, FTM2_BASE_PTR}; //定义三个指针数组保存 FTMn 的地址 /************************************************************************* * 函数名称:FTM_PWM_init * 功能说明:初始化FTM的PWM功能并设置频率、占空比。设置通道输出占空比。 * 参数说明:FTMn 模块号(FTM0、 FTM1、 FTM2) * CHn 通道号(CH0~CH7) * freq 频率(单位为Hz) * duty 占空比 * 备 注:同一个FTM,各通道的PWM频率是一样的,共3个FTM,即可以输出3个不同频率PWM *************************************************************************/ void FTM_PWM_init(FTMn ftmn, CHn ch, u32 freq, u32 duty) { u32 clk_hz = (bus_clk_khz * 1000) >> 1; //bus频率/2 u16 mod; u8 sc_ps; u16 cv; ASSERT( (ftmn == FTM0) || ( (ftmn == FTM1 || ftmn == FTM2 ) && (ch <= CH1)) ); //检查传递进来的通道是否正确 ASSERT( freq <= (clk_hz >> 1) ); //用断言检测 频率 是否正常 ,频率必须小于时钟二分之一 /* 计算频率设置 */ mod = (clk_hz >> 16 ) / freq ; for(sc_ps = 0; (mod >> sc_ps) >= 1; sc_ps++); if(freq < 1000)sc_ps++; mod = (clk_hz >> sc_ps) / freq; if(ftmn==FTM0) cv = (duty * (mod - 0 + 1)) / FTM0_PRECISON; else if(ftmn==FTM1) cv = (duty * (mod - 0 + 1)) / FTM1_PRECISON; else if(ftmn==FTM2) cv = (duty * (mod - 0 + 1)) / FTM2_PRECISON; /******************* 开启时钟 和 复用IO口*******************/ //注,这里代码虽然长,但编译时会删掉很多没用的部分,不影响速度 switch(ftmn) { case FTM0: SIM_SCGC6 |= SIM_SCGC6_FTM0_MASK; //使能FTM0时钟 switch(ch) { case CH0: if(FTM0_CH0 == PTC1) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 1) = PORT_PCR_MUX(4); // PTC1 } else if(FTM0_CH0 == PTA3) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 3) = PORT_PCR_MUX(3); // PTA3 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH1: if(FTM0_CH1 == PTC2) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 2) = PORT_PCR_MUX(4); // PTC2 } else if(FTM0_CH1 == PTA4) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 4) = PORT_PCR_MUX(3); // PTA4 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH2: if(FTM0_CH2 == PTC3) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 3) = PORT_PCR_MUX(4); // PTC3 } else if(FTM0_CH2 == PTA5) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 5) = PORT_PCR_MUX(3); // PTA5 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH3: if(FTM0_CH3 == PTC4) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 4) = PORT_PCR_MUX(4); // PTC4 } else if(FTM0_CH3 == PTA6) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 6) = PORT_PCR_MUX(3); // PTA6 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH4: if(FTM0_CH4 == PTD4) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 4) = PORT_PCR_MUX(4); // PTD4 } else if(FTM0_CH4 == PTA7) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 7) = PORT_PCR_MUX(3); // PTA7 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH5: if(FTM0_CH5 == PTD5) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 5) = PORT_PCR_MUX(4); // PTD5 } else if(FTM0_CH5 == PTA0) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 0) = PORT_PCR_MUX(3); // PTA0 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH6: if(FTM0_CH6 == PTD6) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 6) = PORT_PCR_MUX(4); // PTD6 } else if(FTM0_CH6 == PTA1) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 1) = PORT_PCR_MUX(3); // PTA1 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH7: if(FTM0_CH7 == PTD7) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 7) = PORT_PCR_MUX(4); // PTD7 } else if(FTM0_CH7 == PTA2) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 2) = PORT_PCR_MUX(3); // PTA2 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; default: return; } break; case FTM1: SIM_SCGC6 |= SIM_SCGC6_FTM1_MASK; //使能FTM1时钟 switch(ch) { case CH0: if(FTM1_CH0 == PTA8) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 8) = PORT_PCR_MUX(3); // PTA8 } else if(FTM1_CH0 == PTA12) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 12) = PORT_PCR_MUX(3); // PTA12 } else if(FTM1_CH0 == PTB0) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 0) = PORT_PCR_MUX(3); // PTB0 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH1: if(FTM1_CH1 == PTA9) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 9) = PORT_PCR_MUX(3); // PTA9 } else if(FTM1_CH1 == PTA13) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 13) = PORT_PCR_MUX(3); // PTA13 } else if(FTM1_CH1 == PTB1) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 1) = PORT_PCR_MUX(3); // PTB1 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; default: return; } break; case FTM2: SIM_SCGC3 |= SIM_SCGC3_FTM2_MASK; //使能FTM2时钟 switch(ch) { case CH0: if(FTM2_CH0 == PTA10) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 10) = PORT_PCR_MUX(3); // PTA10 } else if(FTM2_CH0 == PTB18) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 18) = PORT_PCR_MUX(3); // PTB18 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH1: if(FTM2_CH1 == PTA11) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 11) = PORT_PCR_MUX(3); // PTA11 } else if(FTM2_CH1 == PTB19) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 19) = PORT_PCR_MUX(3); // PTB19 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; default: return; } break; default: break; } /******************** 选择输出模式为 边沿对齐PWM *******************/ //通道状态控制,根据模式来选择 边沿或电平 FTM_CnSC_REG(FTMx[ftmn], ch) &= ~FTM_CnSC_ELSA_MASK; FTM_CnSC_REG(FTMx[ftmn], ch) = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK; //MSnB:MSnA = 1x // ELSnB:ELSnA = 10 High-true pulses (clear Output on match) // ELSnB:ELSnA = 11 Low-true pulses (set Output on match) // Edge-aligned PWM 边沿对齐PWM波 《k16 reference manual.pdf》 P944 或者 《K60P144M100SF2RM.pdf》P1001 /******************** 配置时钟和分频 ********************/ FTM_SC_REG(FTMx[ftmn]) = FTM_SC_CPWMS_MASK | FTM_SC_PS(sc_ps) | FTM_SC_CLKS(1); //没有使能溢出中断 FTM_CNTIN_REG(FTMx[ftmn]) = 0; // Channel (n) Value 。设置脉冲宽度:(CnV - CNTIN). FTM_MOD_REG(FTMx[ftmn]) = mod; //Modulo value模数, EPWM的周期为 :MOD - CNTIN + 0x0001 FTM_CNTIN_REG(FTMx[ftmn]) = 0; //Counter Initial Value 计数器初始化值 FTM_CnV_REG(FTMx[ftmn], ch) = cv; FTM_CNT_REG(FTMx[ftmn]) = 0; //计数器。只有低16位可用 } /************************************************************************* * 函数名称:FTM_PWM_Duty * 功能说明:设置通道占空比 * 参数说明:FTMn 模块号(FTM0、 FTM1、 FTM2) * CHn 通道号(CH0~CH7) * duty 占空比 *************************************************************************/ void FTM_PWM_Duty(FTMn ftmn, CHn ch, u32 duty) { u32 cv; u32 mod; ASSERT( (ftmn == FTM0) || ( (ftmn == FTM1 || ftmn == FTM2 ) && (ch <= CH1)) ); //检查传递进来的通道是否正确 if(ftmn==FTM0) ASSERT(duty <= FTM0_PRECISON); //用断言检测 占空比是否合理 else if(ftmn==FTM1) ASSERT(duty <= FTM1_PRECISON); //用断言检测 占空比是否合理 else if(ftmn==FTM2) ASSERT(duty <= FTM2_PRECISON); //用断言检测 占空比是否合理 //占空比 = (CnV-CNTIN)/(MOD-CNTIN+1) mod = FTM_MOD_REG(FTMx[ftmn]); //读取 MOD 的值 if(ftmn==FTM0) cv = (duty * (mod - 0 + 1)) / FTM0_PRECISON; else if(ftmn==FTM1) cv = (duty * (mod - 0 + 1)) / FTM1_PRECISON; else if(ftmn==FTM2) cv = (duty * (mod - 0 + 1)) / FTM2_PRECISON; // 配置FTM通道值 FTM_CnV_REG(FTMx[ftmn], ch) = cv; } /************************************************************************* * 函数名称:FTM_PWM_freq * 功能说明:设置FTM的频率 * 参数说明:FTMn 模块号(FTM0、 FTM1、 FTM2) * freq 频率(单位为Hz) * 函数返回:无 * 备 注:同一个FTM,各通道的PWM频率是一样的,共3个FTM,即可以输出3个不同频率PWM *************************************************************************/ void FTM_PWM_freq(FTMn ftmn, u32 freq) //设置FTM的频率 { u32 clk_hz = (bus_clk_khz * 1000) >> 1; //bus频率/2 u32 mod; u8 sc_ps; ASSERT( freq <= (clk_hz >> 1) ); //用断言检测 频率 是否正常 ,频率必须小于时钟二分之一 /* 计算频率设置 */ mod = (clk_hz >> 16 ) / freq ; for(sc_ps = 0; (mod >> sc_ps) >= 1; sc_ps++); mod = (clk_hz >> sc_ps) / freq; /******************** 配置时钟和分频 ********************/ FTM_SC_REG(FTMx[ftmn]) = FTM_SC_CPWMS_MASK | FTM_SC_PS(sc_ps) | FTM_SC_CLKS(1); //没有使能溢出中断 FTM_CNTIN_REG(FTMx[ftmn]) = 0; // Channel (n) Value 。设置脉冲宽度:(CnV - CNTIN). FTM_MOD_REG(FTMx[ftmn]) = mod; //Modulo value模数, EPWM的周期为 :MOD - CNTIN + 0x0001 FTM_CNTIN_REG(FTMx[ftmn]) = 0; //Counter Initial Value 计数器初始化值 FTM_CNT_REG(FTMx[ftmn]) = 0; //计数器。只有低16位可用 } //////////////////////////////// 以上为输出PWM ////////////////////////////////////////// //////////////////////////////// 以下为输入捕捉 ////////////////////////////////////////// /************************************************************************* * 函数名称:FTM_Input_init * 功能说明:输入捕捉初始化函数 * 参数说明:FTMn 模块号(FTM0、 FTM1、 FTM2) * CHn 通道号(CH0~CH7) * Input_cfg 输入捕捉配置(Rising、Falling、Rising_or_Falling)上升沿捕捉、下降沿捕捉、跳变沿捕捉 * 备 注:CH0~CH3可以使用过滤器,未添加这功能 *************************************************************************/ void FTM_Input_init(FTMn ftmn, CHn ch, Input_cfg cfg) { ASSERT( (ftmn == FTM0) || ( (ftmn == FTM1 || ftmn == FTM2 ) && (ch <= CH1)) ); //检查传递进来的通道是否正确 /******************* 开启时钟 和 复用IO口*******************/ //注,这里代码虽然长,但真正执行的就几条语句 switch(ftmn) { case FTM0: SIM_SCGC6 |= SIM_SCGC6_FTM0_MASK; //使能FTM0时钟 switch(ch) { case CH0: if(FTM0_CH0 == PTC1) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 1) = PORT_PCR_MUX(4); // PTC1 } else if(FTM0_CH0 == PTA3) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 3) = PORT_PCR_MUX(3); // PTA3 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH1: if(FTM0_CH1 == PTC2) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 2) = PORT_PCR_MUX(4); // PTC2 } else if(FTM0_CH1 == PTA4) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 4) = PORT_PCR_MUX(3); // PTA4 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH2: if(FTM0_CH2 == PTC3) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 3) = PORT_PCR_MUX(4); // PTC3 } else if(FTM0_CH2 == PTA5) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 5) = PORT_PCR_MUX(3); // PTA5 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH3: if(FTM0_CH3 == PTC4) { SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, 4) = PORT_PCR_MUX(4); // PTC4 } else if(FTM0_CH3 == PTA6) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 6) = PORT_PCR_MUX(3); // PTA6 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH4: if(FTM0_CH4 == PTD4) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 4) = PORT_PCR_MUX(4); // PTD4 } else if(FTM0_CH4 == PTA7) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 7) = PORT_PCR_MUX(3); // PTA7 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH5: if(FTM0_CH5 == PTD5) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 5) = PORT_PCR_MUX(4); // PTD5 } else if(FTM0_CH5 == PTA0) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 0) = PORT_PCR_MUX(3); // PTA0 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH6: if(FTM0_CH6 == PTD6) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 6) = PORT_PCR_MUX(4); // PTD6 } else if(FTM0_CH6 == PTA1) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 1) = PORT_PCR_MUX(3); // PTA1 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH7: if(FTM0_CH7 == PTD7) { SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 7) = PORT_PCR_MUX(4); // PTD7 } else if(FTM0_CH7 == PTA2) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 2) = PORT_PCR_MUX(3); // PTA2 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; default: return; } break; case FTM1: SIM_SCGC6 |= SIM_SCGC6_FTM1_MASK; //使能FTM1时钟 switch(ch) { case CH0: if(FTM1_CH0 == PTA8) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 8) = PORT_PCR_MUX(3); // PTA8 } else if(FTM1_CH0 == PTA12) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 12) = PORT_PCR_MUX(3); // PTA12 } else if(FTM1_CH0 == PTB0) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 0) = PORT_PCR_MUX(3); // PTB0 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH1: if(FTM1_CH1 == PTA9) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 9) = PORT_PCR_MUX(3); // PTA9 } else if(FTM1_CH1 == PTA13) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 13) = PORT_PCR_MUX(3); // PTA13 } else if(FTM1_CH1 == PTB1) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 1) = PORT_PCR_MUX(3); // PTB1 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; default: return; } break; case FTM2: SIM_SCGC3 |= SIM_SCGC3_FTM2_MASK; //使能FTM2时钟 switch(ch) { case CH0: if(FTM2_CH0 == PTA10) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 10) = PORT_PCR_MUX(3); // PTA10 } else if(FTM2_CH0 == PTB18) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 18) = PORT_PCR_MUX(3); // PTB18 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; case CH1: if(FTM2_CH1 == PTA11) { SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, 11) = PORT_PCR_MUX(3); // PTA11 } else if(FTM2_CH1 == PTB19) { SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, 19) = PORT_PCR_MUX(3); // PTB19 } else { assert_failed(__FILE__, __LINE__); //设置管脚有误? } break; default: return; } break; default: break; } /******************* 设置为输入捕捉功能 *******************/ switch(cfg) { case Rising: //上升沿触发 FTM_CnSC_REG(FTMx[ftmn], 0) |= ( FTM_CnSC_ELSA_MASK | FTM_CnSC_CHIE_MASK ); //置1 FTM_CnSC_REG(FTMx[ftmn], 0) &= ~( FTM_CnSC_ELSB_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_MSA_MASK); //清0 break; case Falling: //下降沿触发 FTM_CnSC_REG(FTMx[ftmn], 0) |= (FTM_CnSC_ELSB_MASK | FTM_CnSC_CHIE_MASK ); //置1 FTM_CnSC_REG(FTMx[ftmn], 0) &= ~( FTM_CnSC_ELSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_MSA_MASK); //清0 break; case Rising_or_Falling: //上升沿、下降沿都触发 FTM_CnSC_REG(FTMx[ftmn], 0) |= ( FTM_CnSC_ELSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_CHIE_MASK ); //置1 FTM_CnSC_REG(FTMx[ftmn], 0) &= ~( FTM_CnSC_MSB_MASK | FTM_CnSC_MSA_MASK); //清0 break; } FTM_SC_REG(FTMx[ftmn]) = FTM_SC_CLKS(0x1); //System clock FTM_MODE_REG(FTMx[ftmn]) |= FTM_MODE_WPDIS_MASK; FTM_COMBINE_REG(FTMx[ftmn]) = 0; FTM_MODE_REG(FTMx[ftmn]) &= ~FTM_MODE_FTMEN_MASK; FTM_CNTIN_REG(FTMx[ftmn]) = 0; FTM_STATUS_REG(FTMx[ftmn]) = 0x00; //清中断标志位 //开启输入捕捉中断 enable_irq(78 - 16 + ftmn); } //**************************************************************************** // FTM2 编码器2 引脚 PTB 18-19 //**************************************************************************** void FTM2_QUAD_Int(void) { PORTB_PCR18 = PORT_PCR_MUX(6); // 设置引脚B18引脚为FTM2_PHA功能 PORTB_PCR19 = PORT_PCR_MUX(6); // 设置引脚B19引脚为FTM2_PHB功能 PORT_PCR_REG(PORTB_BASE_PTR, 18) |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ; //开弱上拉 PORT_PCR_REG(PORTB_BASE_PTR, 19) |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ; //开弱上拉 SIM_SCGC3 |= SIM_SCGC3_FTM2_MASK; // 使能FTM2时钟 FTM2_MODE |= FTM_MODE_WPDIS_MASK; // 写保护禁止 FTM2_QDCTRL |= FTM_QDCTRL_QUADMODE_MASK; // AB相同时确定方向和计数值 FTM2_CNTIN = 0; // FTM0计数器初始值为0 FTM2_MOD = 65535; // 结束值 FTM2_QDCTRL |= FTM_QDCTRL_QUADEN_MASK; // 启用FTM2正交解码模式 FTM2_MODE |= FTM_MODE_FTMEN_MASK; // FTM2EN=1 FTM2_CNT = 0; } //***************************************************************************** // FTM1 编码器1 引脚 PTA 8-9 //***************************************************************************** void FTM1_QUAD_Int(void) { PORTB_PCR0 = PORT_PCR_MUX(6); // 设置引脚A10引脚为FTM2_PHA功能 PORTB_PCR1 = PORT_PCR_MUX(6); // 设置引脚A11引脚为FTM2_PHB功能 PORT_PCR_REG(PORTB_BASE_PTR, 0) |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ; //开弱上拉 PORT_PCR_REG(PORTB_BASE_PTR, 1) |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ; //开弱上拉 SIM_SCGC6 |= SIM_SCGC6_FTM1_MASK; // 使能FTM2时钟 FTM1_MODE |= FTM_MODE_WPDIS_MASK; // 写保护禁止 FTM1_QDCTRL |= FTM_QDCTRL_QUADMODE_MASK; // AB相同时确定方向和计数值 FTM1_CNTIN = 0; // FTM0计数器初始值为0 FTM1_MOD = 65535; // 结束值 FTM1_QDCTRL |= FTM_QDCTRL_QUADEN_MASK; // 启用FTM2正交解码模式 FTM1_MODE |= FTM_MODE_FTMEN_MASK; // FTM2EN=1 FTM1_CNT = 0; }
标签:
原文地址:http://www.cnblogs.com/BlueMountain-HaggenDazs/p/4995766.html