/******************** (C) COPYRIGHT 2011 野火嵌入式开发工作室 ********************
* 文件名 :FTM.c
* 描述 :FTM定时器,目前有 PWM、输入捕捉功能
*
* 实验平台 :野火kinetis开发板
* 库版本 :
* 嵌入系统 :
*
* 作者 :野火嵌入式开发工作室
* 淘宝店 :http://firestm32.taobao.com
* 技术支持论坛 :http://www.ourdev.cn/bbs/bbs_list.jsp?bbs_id=1008
**********************************************************************************/
#include "common.h"
#include "FTM.h"
#include "MK60_port.h"
/*********** FTMn_CHn PWM输出初始化函数 ***********/
/*
--FTM0-- --FTM1-- --FTM2--
CH0 PTC1 PTB0 PTB18
CH1 PTC2 PTB1 PTB19
CH2 PTC3 × ×
CH3 PTC4 × ×
CH4 PTD4 × ×
CH5 PTD5 × ×
CH6 PTD6 × ×
CH7 PTD7 × ×
×表示没有
*/
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 占空比
* 函数返回:无
* 修改时间:2012-2-14
* 备 注:同一个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;
cv = (duty * (mod - 0 + 1)) / FTM_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
{