本文章介绍FTM(FlexTimer)定时器的实现方式
会介绍两种配置方式,实现100ms定时的效果。
寄存器介绍
在此介绍一部分重要的寄存器
SC寄存器
bit9:TOF: 定时器溢出标志位,进入中断函数时,需要首先把TOF位清0 ,否则会一直进入中断函数
bit8:TOIE:使能定时器溢出中断
bit5:CPWMS : 0:向上计数 1:向下计数 通常使用向上计数方式
bit3 - bit4: 配置时钟源
00b - No clock selected. This in effect disables the FTM counter.
01b - FTM input clock
10b - Fixed frequency clock
11b - External clock
bit0 - bit2设置分频系数
000b - Divide by 1
001b - Divide by 2
010b - Divide by 4
011b - Divide by 8
100b - Divide by 16
101b - Divide by 32
110b - Divide by 64
111b - Divide by 128
CNT寄存器
表示计数器的值,因为为16位,所以最大可以加到65535
MOD寄存器
表示定时器的溢出值
CNTIN寄存器
表示定时器计数的初始值,在CNT重新计数时,会从INIT寄存器得到值
外设配置
FTM模块有四个定时器通道,这里使用的是FTM_0,
采用的是系统内部时钟48MHZ,
分频系数128,
Debug mode 选择Mode 0
Timer operation mode 选择Up timer 向上计数
Timer overflow interrupt表示使能计数溢出中断,此处必须勾选,如果仅仅是使用计数功能,可以不勾选
initial value 和 Final value表示计数的初始值和溢出值
此处需要计算一下,如果实现100ms延时,需要知道,分频后的定时器计数频率为375000hz,把100ms转换成秒为0.1S,定时器计数1次的时间为1/375000S,使用0.1除以1/375000为37500,表示需要计数37500次,因为CNT计数器最大计数到16位,所以最大可以计数到65535,所以Final value最大可以填65535,起始值为 65535 - 37500 = 28035
综上,此处initial value为** 28035**,Final value为65535
这样就可以实现100ms定时
同样,还有另外的一种计数方式,如下所示:
此处initial value为** 0**,Final value为37500
这样也可以实现100ms定时
代码部分
#include "sdk_project_config.h"
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include"CLOCK_S32K1xx.h"
#include "interrupt_manager.h"
static int ftm1_cnt= 0 ;
static int ftm2_cnt= 0 ;
void ftmTimerISR_1(void)
{
ftm1_cnt++;
FTM_DRV_ClearStatusFlags(INST_FLEXTIMER_MC_1, FTM_TIME_OVER_FLOW_FLAG); //清除中断
if(ftm1_cnt % 11 == 0)
{
PINS_DRV_TogglePins(PTD,16); //
}
}
void ftmTimerISR_2(void)
{
ftm2_cnt++;
FTM_DRV_ClearStatusFlags(INST_FLEXTIMER_MC_2, FTM_TIME_OVER_FLOW_FLAG); //清除中断
if(ftm2_cnt % 10 == 0)
{
PINS_DRV_TogglePins(PTD,15);
}
}
int main(void)
{
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, 1); // 时钟初始化
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0); //GPIO初始化
ftm_state_t temp_ftm1;
ftm_state_t temp_ftm2;
FTM_DRV_Init(INST_FLEXTIMER_MC_1,&flexTimer_mc_1_InitConfig_0,&temp_ftm1); //FTM0 初始化
FTM_DRV_Init(INST_FLEXTIMER_MC_2,&flexTimer_mc_2_InitConfig_0,&temp_ftm2); //FTM1 初始化
INT_SYS_InstallHandler(FTM0_Ovf_Reload_IRQn,&ftmTimerISR_1,(isr_t*)0); //中断函数配置
INT_SYS_EnableIRQ(FTM0_Ovf_Reload_IRQn); //使能中断函数
INT_SYS_InstallHandler(FTM1_Ovf_Reload_IRQn,&ftmTimerISR_2,(isr_t*)0); //中断函数配置
INT_SYS_EnableIRQ(FTM1_Ovf_Reload_IRQn); //使能中断函数
FTM_DRV_InitCounter(INST_FLEXTIMER_MC_1,&flexTimer_mc_1_TimerConfig_0); //计数初始值配置
FTM_DRV_InitCounter(INST_FLEXTIMER_MC_2,&flexTimer_mc_2_TimerConfig_0); //计数初始值配置
FTM_DRV_CounterStart(INST_FLEXTIMER_MC_1); //计数开始
FTM_DRV_CounterStart(INST_FLEXTIMER_MC_2); //计数开始
while(1)
{
}
}
有几个重点函数:
FTM_DRV_Init对FTM定时器的计数、时钟、模式等进行配置
INT_SYS_InstallHandler配置中断函数
INT_SYS_EnableIRQ使能中断
FTM_DRV_InitCounter配置计数起始值
FTM_DRV_CounterStart计数开始,一般放在最后,
FTM_DRV_ClearStatusFlags清除定时器中断,否则会一直进中断