📄 landzo
字号:
u32 cv;
u32 mod;
ASSERT( (ftmn == FTM0) || ( (ftmn == FTM1 || ftmn == FTM2 ) && (ch <= CH1)) ); //检查传递进来的通道是否正确
ASSERT(duty <= FTM_PRECISON); //用断言检测 占空比是否合理
//占空比 = (CnV-CNTIN)/(MOD-CNTIN+1)
mod = FTM_MOD_REG(FTMx[ftmn]); //读取 MOD 的值
cv = (duty * (mod - 0 + 1)) / FTM_PRECISON;
// 配置FTM通道值
FTM_CnV_REG(FTMx[ftmn], ch) = cv;
}
/*************************************************************************
* 野火嵌入式开发工作室\蓝宙电子工作室
*
* 函数名称:FTM_PWM_freq
* 功能说明:设置FTM的频率
* 参数说明:FTMn 模块号(FTM0、 FTM1、 FTM2)
* freq 频率(单位为Hz)
* 函数返回:无
* 修改时间:2012-2-14
* 备 注:同一个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)上升沿捕捉、下降沿捕捉、跳变沿捕捉
* 函数返回:无
* 修改时间:2012-1-26
* 备 注: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(PORTA_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(PORTA_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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -