rt1064内部有2个通用定时器,两个定时器完全独立。
定时器框图基本功能如下
重启模式:
在重启模式下(通过GPT控制寄存器GPT_CR可选择),当计数器达到比较值时,计数器重置并从0x00000000开始重新启动。重启特性只与比较通道1相关联。
对通道1的Compare寄存器的任何写访问都将重置GPT计数器。这样做是为了避免在计数过程中将比较值从较高值更改为较低值时可能丢失比较事件。
对于另外两个比较通道,当比较事件发生时,计数器不会重置。
自由运行模式:
在自由运行模式下,当三个通道发生比较事件时,计数器不复位;相反,计数器继续计数直到0xffffffff,然后滚动(到0x00000000)。
OM1[2:0]位,用于设置匹配时间是否输出到IO口上
000,不输出到 IO;
001,IO 取反;
010,IO 输出低电平;
011,IO 输出高电平;
1xx,产生一个低电平脉冲,脉宽
为 1 个输入时钟周期(分频器之前的时钟)。
用于设置软件复位 GPT 定时器。设置为 1,即可复位 GPT 定时器,复位完成后,
自动清零该位。
FRR 位,用于设置匹配事件 1 发生时的工作模式。0,复位模式;1,自由运行模式。
CLKSRC[2:0]位,用于选择 GPT 定时器的输入时钟源。我们一般设置 CLKSRC[2:0]=1,即
选择外设时钟(ipg_clk)作为时钟源。注意:这里的 ipg_clk 实际上是指 PERCLK_CLK_ROOT, 即 75Mhz
DBGEN 位,用于设置 GPT 定时器在 debug 模式下是否正常运行。我们一般设置该位为 1,
即在 debug 模式下,GPT 定时器也是正常运行的。
EN 位,用于设置 GPT 定时器的使能。0,禁止;1,使能;该位一般在配置的最后才设置。
预分频寄存器
输出比较寄存器1
该寄存器用于设置 GPT 定时器比较通道 1 的比较值。一个 GPT 定时器总共有 3 个这样的寄存器:GPTx_OCR1~GPTx_OCR2,分别对应输出比较通道 1/2/3。本章我们使用重启模式,设置该寄存器的值,就可以控制定时器的溢出时间,从而实现固定周期中断功能。
假设我们选择 PERCLK_CLK_ROOT 作为时钟源(CLKSRC[2:0]=1),则 GPT 定时器的溢
出时间计算公式为:
T o u t = o c r _ 1 ∗ ( p s c + 1 ) P E R C L K _ C L K _ R O O T Tout = \frac{ocr\_1 * (psc+1)}{ PERCLK\_CLK\_ROOT } Tout=PERCLK_CLK_ROOTocr_1∗(psc+1)
T o u t Tout Tout:GPT 定时器溢出时间,单位 us
o c r _ 1 ocr\_1 ocr_1:输出比较 1(GPTx_OCR1)寄存器的设置值
p s c psc psc:预分频值(由 GPTx_PR 的 PRESCALER[11:0]位设置),取值范围为 0~4095
P E R C L K _ C L K _ R O O T PERCLK\_CLK\_ROOT PERCLK_CLK_ROOT:GPTx 定时器的时钟源(通过 CLKSRC[2:0]=1 设置),单位:Mhz,
一般为 75Mhz。
假设 ocr1=10000,psc=3749,则 定 时 器 溢 出 时 间 = 3750 ∗ 10000 / 75 = 500000 u s = 0.5 s 定时器溢出时间=3750*10000/75= 500000us=0.5s 定时器溢出时间=3750∗10000/75=500000us=0.5s
中断控制寄存器
GPTx_IR 寄存器总共有 6 个有效位,分别控制溢出、2 路输入捕获和 3 路输出比较中断的使能和关闭。
1:使能 0:失能
ROVIE[5]:溢出中断
IFxIE:输入捕获中断
OFxIE:输出比较中断
GPT 相关的库函数在 fsl_gpt.c 和 fsl_gpt.h 这两个文件中
GPT配置步骤
通过函数 CLOCK_EnableClock 来使能 GPT1 时钟,GPT 初始化函数 GPT_Init 默认会使能GPT 使能,所以不需要我们显式的相应函数来使能 GPT 时钟。
GPT 的初始化使用函数 GPT_Init
void GPT_Init(GPT_Type *base, const gpt_config_t *initConfig)
{
assert(NULL != initConfig);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate the GPT clock*/
CLOCK_EnableClock(s_gptClocks[GPT_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
base->CR = 0U;
GPT_SoftwareReset(base);
base->CR =
(initConfig->enableFreeRun ? GPT_CR_FRR_MASK : 0UL) | (initConfig->enableRunInWait ? GPT_CR_WAITEN_MASK : 0UL) |
(initConfig->enableRunInStop ? GPT_CR_STOPEN_MASK : 0UL) |
(initConfig->enableRunInDoze ? GPT_CR_DOZEEN_MASK : 0UL) |
(initConfig->enableRunInDbg ? GPT_CR_DBGEN_MASK : 0UL) | (initConfig->enableMode ? GPT_CR_ENMOD_MASK : 0UL);
GPT_SetClockSource(base, initConfig->clockSource);
GPT_SetClockDivider(base, initConfig->divider);
}
GPT_Type *base
:GPT1或者GPT2,在MIMXRT1064.h中21006中
/* GPT - Peripheral instance base addresses */
/** Peripheral GPT1 base address */
#define GPT1_BASE (0x401EC000u)
/** Peripheral GPT1 base pointer */
#define GPT1 ((GPT_Type *)GPT1_BASE)
/** Peripheral GPT2 base address */
#define GPT2_BASE (0x401F0000u)
/** Peripheral GPT2 base pointer */
#define GPT2 ((GPT_Type *)GPT2_BASE)
/** Array initializer of GPT peripheral base addresses */
#define GPT_BASE_ADDRS { 0u, GPT1_BASE, GPT2_BASE }
/** Array initializer of GPT peripheral base pointers */
#define GPT_BASE_PTRS { (GPT_Type *)0u, GPT1, GPT2 }
/** Interrupt vectors for the GPT peripheral type */
#define GPT_IRQS { NotAvail_IRQn, GPT1_IRQn, GPT2_IRQn }
const gpt_config_t *initConfig
:数设置 GPT 定时器的配置参数
/*! @brief Structure to configure the running mode. */
typedef struct _gpt_init_config
{
gpt_clock_source_t clockSource; /*!< clock source for GPT module. */
uint32_t divider; /*!< clock divider (prescaler+1) from clock source to counter. */
bool enableFreeRun; /*!< true: FreeRun mode, false: Restart mode. 自由运行重置模式*/
bool enableRunInWait; /*!< GPT enabled in wait mode. */
bool enableRunInStop; /*!< GPT enabled in stop mode. */
bool enableRunInDoze; /*!< GPT enabled in doze mode. */
bool enableRunInDbg; /*!< GPT enabled in debug mode. */
bool enableMode; /*!< true: counter reset to 0 when enabled;
false: counter retain its value when enabled. */
} gpt_config_t;
第一个结构体参数clockSource
:选择时钟源,配置CR 寄 存 器 的 CLKSRC 位
一般选择外设时钟kGPT_ClockSource_Periph (ipg_clk)作为 GPT 的时钟源
/*!
* @brief List of clock sources
* @note Actual number of clock sources is SoC dependent
*/
typedef enum _gpt_clock_source
{
kGPT_ClockSource_Off = 0U, /*!< GPT Clock Source Off.*/
kGPT_ClockSource_Periph = 1U, /*!< GPT Clock Source from Peripheral Clock.*/
kGPT_ClockSource_HighFreq = 2U, /*!< GPT Clock Source from High Frequency Reference Clock.*/
kGPT_ClockSource_Ext = 3U, /*!< GPT Clock Source from external pin.*/
kGPT_ClockSource_LowFreq = 4U, /*!< GPT Clock Source from Low Frequency Reference Clock.*/
kGPT_ClockSource_Osc = 5U, /*!< GPT Clock Source from Crystal oscillator.*/
} gpt_clock_source_t;
第二个结构体参数divider
:分频系数,值0-4095
GPT_Init 一般的使用方法如下:
gpt_config_t gpt1_onfig;
GPT_GetDefaultConfig(&gpt1_onfig); //先初始化 GPT1 为默认值
gpt1_onfig.clockSource=kGPT_ClockSource_Periph; //初始化时钟源 perclk_clk_root
gpt1_onfig.divider=psc; //设置分频值
GPT_Init(GPT1,&gpt1_onfig); //初始化 GPT1
GPT_GetDefaultConfig函数的具体情况
void GPT_GetDefaultConfig(gpt_config_t *config)
{
assert(NULL != config);
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
config->clockSource = kGPT_ClockSource_Periph;
config->divider = 1U;
config->enableRunInStop = true;
config->enableRunInWait = true;
config->enableRunInDoze = false;
config->enableRunInDbg = false;
config->enableFreeRun = false;
config->enableMode = true;
}
在上面代码中我们先调用函数 GPT_GetDefaultConfig 将 GPT 的配置参数结构体设置为默认值,然后在根据实际情况修改。
GPT1 比较值的设定通过函数 GPT_SetOutputCompareValue 来完成
static inline void GPT_SetOutputCompareValue(GPT_Type *base, gpt_output_compare_channel_t channel, uint32_t value)
{
assert(channel <= kGPT_OutputCompare_Channel3);
base->OCR[(uint32_t)channel] = value;
}
``
GPT_Type *base
:GPT1或者GPT2,在MIMXRT1064.h中21006中
gpt_output_compare_channel_t channel
:
typedef enum _gpt_output_compare_channel
{
kGPT_OutputCompare_Channel1 = 0U, //输出比较通道 1
kGPT_OutputCompare_Channel2 = 1U, //输出比较通道 2
kGPT_OutputCompare_Channel3 = 2U, //输出比较通道 3
} gpt_output_compare_channel_t;
uint32_t value
:比较值
输出比较中断设置通过函数 GPT_EnableInterrupts 来完成
/*!
* @brief Enables the selected GPT interrupts.
*
* @param base GPT peripheral base address.
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::gpt_interrupt_enable_t
*/
static inline void GPT_EnableInterrupts(GPT_Type *base, uint32_t mask)
{
base->IR |= mask;
}
中断可选参数
/*! @brief List of GPT interrupts */
typedef enum _gpt_interrupt_enable
{
kGPT_OutputCompare1InterruptEnable = GPT_IR_OF1IE_MASK, /*!< Output Compare Channel1 interrupt enable*/
kGPT_OutputCompare2InterruptEnable = GPT_IR_OF2IE_MASK, /*!< Output Compare Channel2 interrupt enable*/
kGPT_OutputCompare3InterruptEnable = GPT_IR_OF3IE_MASK, /*!< Output Compare Channel3 interrupt enable*/
kGPT_InputCapture1InterruptEnable = GPT_IR_IF1IE_MASK, /*!< Input Capture Channel1 interrupt enable*/
kGPT_InputCapture2InterruptEnable = GPT_IR_IF2IE_MASK, /*!< Input Capture Channel1 interrupt enable*/
kGPT_RollOverFlagInterruptEnable = GPT_IR_ROVIE_MASK, /*!< Counter rolled over interrupt enable*/
} gpt_interrupt_enable_t;
GPT 设置好以后就可以调用函数 GPT_StartTimer 来使能 GPT 定时器了
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Start GPT timer.
*
* @param base GPT peripheral base address.
*/
static inline void GPT_StartTimer(GPT_Type *base)
{
base->CR |= GPT_CR_EN_MASK;
}
失能定时器
/*!
* @brief Stop GPT timer.
*
* @param base GPT peripheral base address.
*/
static inline void GPT_StopTimer(GPT_Type *base)
{
base->CR &= ~GPT_CR_EN_MASK;
}
GPT1_IRQn = 100, /**< GPT1 interrupt */
GPT2_IRQn = 101, /**< GPT2 interrupt */
中断号
编写定时器中断服务函数
中断状态获取函数 GPT_GetStatusFlags
static inline uint32_t GPT_GetStatusFlags(GPT_Type *base, gpt_status_flag_t flags)
{
return base->SR & (uint32_t)flags;
}
可选的中断标志位
这些位通过写入1来清除标志位
/*! @brief List of GPT interrupts */
typedef enum _gpt_status_flag
{
kGPT_OutputCompare1Flag = GPT_SR_OF1_MASK, //输出比较通道 1 中断标志
kGPT_OutputCompare2Flag = GPT_SR_OF2_MASK, //输出比较通道 2 中断标志
kGPT_OutputCompare3Flag = GPT_SR_OF3_MASK, //输出比较通道 3 中断标志
kGPT_InputCapture1Flag = GPT_SR_IF1_MASK, //输入捕获通道 1 中断标志
kGPT_InputCapture2Flag = GPT_SR_IF2_MASK, //输入捕获通道 2 中断标志
kGPT_RollOverFlag = GPT_SR_ROV_MASK, //溢出中断标志
} gpt_status_flag_t;
中断状态(标志位)清除函数 GPT_ClearStatusFlags
gpt_config_t gpt1_onfig;
//初始化 GPTIMER1,时钟源为 perclk_clk_root=75MHz
//pre:分频值,0~4096
//comcount:比较计数值,0~0xFFFFFFFF
//当 ocrx==CNT 时,产生中断.
//定时时间=ocrx*(psc+1)/PERCLK_CLK_ROOT
void GPT1_Int_Init(u16 psc,u32 ocrx)
{
GPT_GetDefaultConfig(&gpt1_onfig); //先初始化 GPT1 为默认值
gpt1_onfig.clockSource=kGPT_ClockSource_Periph; //初始化时钟源 perclk_clk_root
gpt1_onfig.divider=psc; //设置分频值
GPT_Init(GPT1,&gpt1_onfig);
//设置比较计数值
GPT_SetOutputCompareValue(GPT1,kGPT_OutputCompare_Channel1,ocrx);
//使能 GPT 比较通道 1 中断
GPT_EnableInterrupts(GPT1,kGPT_OutputCompare1InterruptEnable);
RT1052_NVIC_SetPriority(GPT1_IRQn,5,0); //抢占优先级 5,子优先级 0
EnableIRQ(GPT1_IRQn); //使能 GPT1 中断
GPT_StartTimer(GPT1); //开始定时器
}
//GPT1 中断服务函数
void GPT1_IRQHandler(void)
{
//OCR1 中断
if(GPT_GetStatusFlags(GPT1,kGPT_OutputCompare1Flag))
{
LED1_Toggle; //LED1 灯翻转
GPT_ClearStatusFlags(GPT1,kGPT_OutputCompare1Flag);//清除中断标志位
}
__DSB(); //数据同步屏蔽指令
}
本文参照正点原子RT1052 开发指南修改编辑。
作者的软件基于逐飞部分库和fsl库开发