本帖最后由 洋葱圈 于 2013-11-18 16:53 编辑
输入捕获功能
IC工作原理IC就是Input Capture的英文缩写,即输入捕获。很多新手不仅疑惑FTM,还疑惑他怎么还有这么多功能,更疑惑这么多功能中输入捕获到底干什么用。首先FTM为什么除了能生成PWM,还有其他功能,这都是因为他有这么多给力的小伙伴(寄存器),上面介绍那些小朋友不仅能生成PWM,还能利用自身特长,摇身一变成输入捕获功能。那么输入捕获有什么用呢,输入什么?捕获什么?他就像PWM的逆变一样,通过输入PWM方波,捕获上升沿或者下降沿,来计算出PWM的频率或者占空比。
那么这几个小朋友是怎么工作,来实现输入捕获功能的呢,且听我一一道来。首先CnV小朋友不再负责记住一个数了,而是随时待命,随时准备记录下CNT小朋友喊的数字。当FTM的输入通道产生一个上升沿或者下降沿的时候,就会产生一个中断,这是CnV小朋友就会立刻记录下CNT小朋友喊的数字,我们只要知道两次中断之间CnV小朋友记录的计数的差,就可以间接计算出中断间隔时间了,从而可以计算出PWM方波的频率。当然CNT小朋友喊号的频率还是有SC小朋友决定的。假设我们知道CNT喊号的频率为fCNT,CnV自从上次中断后记录的计数差为cv,配置捕获上升沿时产生中断,那么两次中断的时间差的倒数就是PWM方波的频率: 输入PWM频率=fCNT/cv 同样还是来看一下我从技术文档中截下来的图,原图初出自Figure 39-175。红框圈出来的是FTM的通道输入,这个通道在物理引脚上和PWM的输出通道是共用的,只不过随着功能的不同,输入输出都可以。橙色圈代表的是判断到底是上升沿还是下降沿来触发冲断。深色绿圈代表了CnV在这个事件来临的时候记录下CNT的数值,浅绿色是CNT计数器的值。蓝色圈代表我们即将产生的中断信号。
IC例程讲解打开例程“LPLD_InputCapture”,在这里例程中,我们利用FTM0生成一路PWM,用于测试他的频率,用FTM1配置为输入捕获模块,来采集PWM并计算他的频率。pwm_init()初始化函数的代码我们就不赘述了,相信大家都能看懂,直接看下输入捕获的初始化函数ic_init()的代码:
1 | ftm1_init_struct.FTM_Ftmx = FTM1; //使能FTM1通道 | 2 | ftm1_init_struct.FTM_Mode = FTM_MODE_IC; //使能输入捕获模式 | 3 | ftm1_init_struct.FTM_ClkDiv = FTM_CLK_DIV128; //计数器频率为总线时钟的128分频 | 4 | ftm1_init_struct.FTM_Isr = ic_isr; //设置中断函数 | 5 | LPLD_FTM_Init(ftm1_init_struct); | 6 | LPLD_FTM_IC_Enable(FTM1, FTM_Ch0, PTB0, CAPTURE_RI); | 7 | LPLD_FTM_EnableIrq(ftm1_init_struct); |
Line 2:配置FTM1为输入捕获模式。
Line 3:设置计数器的分频系数为128,刚才我们讲过要计算PWM的频率,就要知道CNT计数器的频率,在OSKinetis固件库中,CNT的时钟源为总线时钟,如果这里设置为FTM_CLK_DIV128,那么CNT的频率就是总线频率/128。
Line 4:设置FTM的中断函数,用于处理捕获事件。
Line 6:使能输入捕获的输入通道,和PWM的使能通道同理,这里要设置需要用到的通道号为FTM_Ch0,通道对应的物理引脚为PTB0,捕获边缘为上升沿CAPTURE_RI。关于此函数的参数的具体范围,请参考FTM模块的在线函数手册(点击进入)。
Line 7:一定要记住使能中断。
输入捕获初始化完毕后,FTM1就会在PTB0有输入PWM的时候产生中断了,接下来看一下其中断函数是怎么写的:
01 | void ic_isr(void) | 02 | { | 03 | uint32 cnt; | 04 | if(LPLD_FTM_IsCHnF(FTM1, FTM_Ch0)) | 05 | { | 06 | cnt=LPLD_FTM_GetChVal(FTM1, FTM_Ch0); | 07 | Freq1=(g_bus_clock/LPLD_FTM_GetClkDiv(FTM1))/cnt; | 08 | LPLD_FTM_ClearCounter(FTM1); | 09 | LPLD_FTM_ClearCHnF(FTM1, FTM_Ch0); | 10 | } | 11 | } |
Line 4:首先调用LPLD_FTM_IsCHnF()函数判断是不是FTM1的Ch0通道产生的捕获事件,因为每个FTMx的所有通道中断都是公用一个中断函数的,所以为了安全,必须在中断中判断是哪个通道产生的中断。
Line 6:获得Ch0通道的计数值,并存到临时变量cnt中。这个值就是C0V小朋友在事件来临的一瞬间,从CNT那里记录下来的计数值。
Line 7:用上将讲到的频率计算公式来计算出PWM的频率。这里LPLD_FTM_GetClkDiv()可以得到我们初始化时设置的计数器分频系数,g_bus_clock变量是总线频率的数值,用(g_bus_clock/LPLD_FTM_GetClkDiv(FTM1))就得到了计数器CNT的技术频率,在除以cnt计数值,得到的就是输入方波的频率。
Line 8:用LPLD_FTM_ClearCounter()函数清空CNT小朋友的计数值,以便我们下次中断获取的值是从0开始的,方便计算。
Line 9:用LPLD_FTM_ClearCHnF()函数清除Ch0通道的中断标志。
正交解码
正交解码原理讲到正交解码,其实并没有什么神秘的,名字听起来挺高端大气上档次的,其实实现起来非常简单,我觉得反而是FTM模块中最简单的功能。首先要清楚正交解码是干嘛用的,举个栗子?霍尔编码器是常用的电机测速传感器,他不仅可以测速,还可以知道电机的正转还是反转,靠的就是他能输出两路正交信号,我们可以通过正交信号的相位差来识别出当前电机的转动方向。因此有了FTM模块,我们就可以将这两路正交信号PhA和PhB输入到FTM的正交输入通道,通过正交解码功能,直接读取脉冲的计数值,这个计数值是有符号的,正数代表正转,负数则代表反转。 具体到FTM内部时怎样工作的,还要提到CNT小朋友,在正交解码模式下,他不再按照SC给定的规则喊号了,而是根据两路PhA和PhB正交信号的状态来计数。你也可以理解为CNT小朋友是一个解码员,当然具体是增计数还是减计数,不是CNT说了算,FTM内部有一套复杂的机制决定。而且这个正交解码功能有两种解码方法可以选择,分别是计数和方向编码、相位A和相位B编码。他们的解码方法如下面两图所示:
上图是计数和方向编码方法,红框后面的波形是FTM输入通道PhB的波形,它代表计数方向,篮框后面的波形是FTN输入通道PhA的波形,它代表计数个数,这是一种编码方法,当PhB为高电平时,CNT加计数,当PhB低电平时,CNT减计数,计数频率由PhA决定。从图中还可以看出,CNTIN小朋友决定从什么数开始计数,MOD小朋友决定计数到什么时候产生溢出中断。
上图是相位A和相位B编码方法,这个是我们常用的正交解码模式,也是霍尔编码传感器两路波形输出的方式。从图中可以看到,当PhA和PhB处于特定的电平和边沿时,他们的状态共同决定了CNT是增还是减。具体原则如下:
CNT小朋友增计数时看到的是:
A上升沿,B逻辑低
B上升沿,A逻辑高
B下降沿,A逻辑低
A下降沿,B逻辑高
CNT小朋友减计数时看到的是:
A下降沿,B逻辑低
B下降沿,A逻辑高
B上升沿,A逻辑低
A上升沿,B逻辑高
正交解码例程讲解要测试正交解码例程,首先你要准备两路正交信号,可以用霍尔编码器的信号直接输入。打开例程“LPLD_QuadratureDecoder”,看正交解码初始化函数qd_init()的代码:
1 | ftm_init_struct.FTM_Ftmx = FTM1; //只有FTM1和FTM2有正交解码功能 | 2 | ftm_init_struct.FTM_Mode = FTM_MODE_QD; //正交解码功能 | 3 | ftm_init_struct.FTM_QdMode = QD_MODE_PHAB; //AB相输入模式 | 4 | LPLD_FTM_Init(ftm_init_struct); | 5 | LPLD_FTM_QD_Enable(FTM1, PTB0, PTB1); |
Line 2:配置FTM1为正交解码功能,这里需要注意的是,FTM中只有FTM1和FTM2具有正交解码输入通道,FTM0是没有的。
Line 3:选择解码模式为AB相输入模式解码QD_MODE_PHAB。
Line 5:使能FTM1的正交解码物理输入引脚,调用LPLD_FTM_QD_Enable()函数,第二个参数是PhA相的物理引脚,第三个参数的PhB的。关于此函数的参数的具体范围,请参考FTM模块的在线函数手册(点击进入)。 正交解码初始化完毕后,还要初始化定时中断模块,因为我们要在固定的间隔时间内获取计数值才能计算出频率,所以就务必会用到PIT模块。pit_init()函数是PIT初始化函数,相信大家都能读懂,这里我就不重复解释了。下面直接看PIT的中断函数代码:
1 | qd_result = LPLD_FTM_GetCounter(FTM1); | 2 | LPLD_FTM_ClearCounter(FTM1); |
Line 1:LPLD_FTM_GetCounter()函数可以获取当前FTM计数器即CNT小朋友的计数值,当然这个值是有符号的,可以正可以是负数。如果是正代表电机在正转,如果是负,代表电机在反转。
Line 2:为了下次方便计数,情况CNT的计数值。
当然,本例程只是简单的获取计数值,如果你要计算频率,还用通过你的定时中断时间进一步计算。
FTM拾遗补缺
PWM死区PWM死去是在是PWM输出时,为了使H桥或半H桥的上下管不会因为器件本身的开关速度问题导致同时导通而设置的一个保护时段。这个时间在Kinetis的FTM模块也是可以设置的,当然在库函数使用时就更简单了,你只要在配置PWM输出时,配置FTM_PwmDeadtimeCfg和FTM_PwmDeadtimeDiv就可以了。这两个成员变量的取值本文不再赘述,请参考在线函数手册。
溢出中断除了输入捕获能产生中断外,FTM内部也会产生溢出中断,这是你在使用输入捕获或者正交解码时可能遇到的问题,那么什么是溢出中断呢,它是当CNT计数器计数到上限时产生的一种中断。你可以在初始化FTM时配置是否使能该中断,利用成员变量FTM_ToiEnable。
|