文章目录
- 1 通用定时器
- 1.1 定时器框图
- 1.2 实现周期性中断
- 2 相关寄存器
- 3 定时器配置
- 3.1 时钟使能
- 3.2 初始化GPT1定时器
- 3.2.1 base
- 3.2.2 initConfig
- 3.2.2.1 clockSorce
- 3.2.2.2 divider
- 3.2.2.3 enablexxxxx
- 3.3 设置 GPT1 比较值
- 3.3.1 base
- 3.3.2 channel
- 3.3.3 value
- 3.4 设置 GPT1 输出比较 1 的 中断
- 3.5 使能 GPT
- 3.6 设置 GPT1 中断 优先级
- 3.7 编写中断服务函数
- 3.7.1 GPT_GetStatusFlags
- 3.7.2 GPT_ClearStatusFlags
- 3.8 最终代码
1 通用定时器
RT1052 内部包含 2 个通用定时器(GPT1 和 GPT2,以下简称 GPT)
1.1 定时器框图
一个 32 位定时器,拥有 2 个输入捕获通道、3 个输出比较通道以及相应的中断。
1)32 位计数器(CNT),仅支持递增计数方式。
2)12 位可编程预分频器(PR),计数器时钟频率的分频系数为 1~4096 之间的任意数值。
3)2 个输入捕获通道,支持上升沿、下降沿和任意边沿捕获。
4)3 个输出比较通道,支持取反、设置、清零和生成单脉冲(1 个输入时钟)模式。
5)支持捕获、比较和溢出中断。
6)支持低功耗模式下继续运行。
6)支持重启(Restart)模式和自由运行(Free Run)模式
- 重启模式:当计数器值与比较值匹配时,计数器自动清零,重新开始计数。
- 自由运行模式:计数器值总是从 0 开始计数,一直到 0XFFFFFFFF 溢出,发生匹配事件不会导致定时器清零。
1.2 实现周期性中断
使用重启模式,利用比较值1 来设置溢出时间
2 相关寄存器
3 定时器配置
GPT 相关的库函数在 fsl_gpt.c 和 fsl_gpt.h 这两个文件中
3.1 时钟使能
GPT 初始化函数 GPT_Init 默认会使能GPT 使能。函数里面通过 CLOCK_EnableClock 来使能了 GPT1 时钟。
3.2 初始化GPT1定时器
void GPT_Init(GPT_Type *base, const gpt_config_t *initConfig)
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
3.2.1 base
GPT1
3.2.2 initConfig
typedef struct _gpt_init_config
{
gpt_clock_source_t clockSource; //选择时钟源
uint32_t divider; //时钟源分频
bool enableFreeRun;
bool enableRunInWait;
bool enableRunInStop;
bool enableRunInDoze;
bool enableRunInDbg;
bool enableMode;
} gpt_config_t;
3.2.2.1 clockSorce
clockSource 用来设置用于 GPT 的时钟源
typedef enum _gpt_clock_source
{
kGPT_ClockSource_Off = 0U, //关闭时钟
kGPT_ClockSource_Periph = 1U, //外设时钟(ipg_clk)
kGPT_ClockSource_HighFreq = 2U, //高速参考时钟(ipg_clk_highfreq)
kGPT_ClockSource_Ext = 3U, //外部参考时钟
kGPT_ClockSource_LowFreq = 4U, //低速参考时钟(ipg_clk_32k)
kGPT_ClockSource_Osc = 5U, //24M 晶振
} gpt_clock_source_t;
实 际 上 设 置 的 是 CR 寄 存 器 的 CLKSRC 位 , 一 般 选 择 外 设 时 钟
kGPT_ClockSource_Periph (ipg_clk)作为 GPT 的时钟源
- 外设时钟配置一般为75Mhz。
3.2.2.2 divider
divider 设置时钟源分频,可以设置的值范围为 0~4095,分别对应 1~4096 分频。
- 实际设置的是 PR 寄存器的 PRESCALER 位
- 比如我们将分频值设置为 2,那么 GPT1 最终的时钟就是:75MHz/(2+1)=25MHz。
3.2.2.3 enablexxxxx
使能 GPT 的相应模式
3.3 设置 GPT1 比较值
设置好比较值就可以决定确定GPT1的溢出时间了,也就是定时时间。
- GPT1 比较值的设定通过函数 GPT_SetOutputCompareValue 来完成
static inline void GPT_SetOutputCompareValue(GPT_Type *base,gpt_output_compare_channel_t channel,uint32_t value)
3.3.1 base
GPT1
3.3.2 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;
3.3.3 value
第三个参数就是要设置的比较值。
- 比如我们设置 GPT1 分频值为 3749
- 那么GPT1 的时钟就是 75MHz/(3749+1)=20000Hz
- 比较值设置为 10000 的话那么每 0.5s 就会产生一次比较中断,这样就实现了 0.5s 的定时。
3.4 设置 GPT1 输出比较 1 的 中断
输出比较中断设置通过函数 GPT_EnableInterrupts 来完成
GPT_EnableInterrupts(GPT_Type *base, uint32_t mask);
GPT_EnableInterrupts(GPT1, kGPT_OutputCompare1InterruptEnable);
使用 GPT1 的输出比较通道 1,所以设置为 kGPT_OutputCompare1InterruptEnable。
3.5 使能 GPT
调用函数 GPT_StartTimer 来使能 GPT 定时器
void GPT_StartTimer(GPT_Type *base)
设置 CR 寄存器的 EN 位
3.6 设置 GPT1 中断 优先级
因为要产生中断,必不可少的要设置 NVIC 相关寄存器
RT1052_NVIC_SetPriority(GPT1_IRQn,5,0); //抢占优先级 5,子优先级 0
EnableIRQ(GPT1_IRQn); //使能 GPT1 中断
3.7 编写中断服务函数
中断产生后,需要通过函数 GPT_GetStatusFlags 判断是否为比较中断。在处理完中断之后调用函数 GPT_ClearStatusFlags 来清除该中断标志。
3.7.1 GPT_GetStatusFlags
static inline uint32_t GPT_GetStatusFlags(GPT_Type *base, gpt_status_flag_t flags)
- GPT1
- flags
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;
3.7.2 GPT_ClearStatusFlags
中断状态(标志位)清除函数 GPT_ClearStatusFlags 原型如下:
static inline void GPT_ClearStatusFlags(GPT_Type *base, gpt_status_flag_t flags)
- GPT1
- kGPT_OutputCompare1Flag。
3.8 最终代码
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_EnableInterrupts(GPT1,kGPT_OutputCompare1InterruptEnable); //使能GPT比较通道1中断
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(); //数据同步屏蔽指令
}