I.MX6U 裸机开发18.GPT定时器实现高精度延时

摘要:IMX6ULL 的GPT定时器(General Purpose Timer)是一种通用定时器,可以用于生成精确的时间延迟、测量时间间隔、产生周期性中断等,以下是它的几个特性:

IMX6ULL 的GPT定时器(General Purpose Timer)是一种通用定时器,可以用于生成精确的时间延迟、测量时间间隔、产生周期性中断等,以下是它的几个特性:

GPT 有一个 32 位的向上计数器。定时器的计数值可以通过外部引脚上的事件被捕获到一个寄存器中。捕获触发可以被编程为上升沿和/或下降沿。GPT 还可以在输出比较引脚上生成一个事件,并在定时器达到编程值时产生一个中断。GPT 有一个 12 位的预分频器,它从多个时钟源中提供一个可编程的时钟频率。

相比较,EPIT:


本文使用 ipg_clk 作为时钟源,即66MHz。

从左上角开始,输入时钟时钟进入 Prescaler 12位分频器(值0~4095)分频后进入 Timer Counter,即32位计数器GET_CAPTURE1, GET_CAPTURE2 实现捕获功能TIMER Output Reg1~3, 是三路时钟输出,Timer Count要与这三路值进行比较,GET_COMPARE1~3,三路比较输出

自由运行模式,计数器从零开始计数,并在达到最大值后回到零,继续计数。这个模式通常用于测量时间间隔或生成周期性中断。
比较的时候,是比较定时器的计数值和比较寄存器OCR。

输入捕获模式,计数器在检测到外部事件(如信号边沿)时捕获当前计数值,并将其存储在捕获寄存器中。这个模式通常用于测量外部事件的时间间隔。

特点:

计数器在检测到外部事件时捕获当前计数值。可以配置中断,在捕获事件发生时触发中断。三个通道都适用, 从0开始一直加到 0xFFFFFFFF,然后重新从0开始。

计数器达到其最大值并回到零时,会触发溢出中断。这个中断通常用于周期性任务或需要精确时间间隔的应用。

可以捕获外部事件的时间戳。GPT有两个输入捕获通道,分别为输入捕获中断1(Input Capture Interrupt 1)和输入捕获中断2(Input Capture Interrupt 2)。

在计数器达到预设值时触发中断。GPT有三个输出比较通道,分别为输出比较中断1(Output Compare Interrupt 1)、输出比较中断2(Output Compare Interrupt 2)和输出比较中断3(Output Compare Interrupt 3)。

GPTx_CR 是 GPT的控制寄存器,用于配置和控制 GPT 定时器的各种功能。以下是 GPTx_CR 寄存器的各个功能位的详细说明:

bit 0

GPT Enable: 使能GPT定时器,1使能

bit 1

GPT Enable Mode: 使能模式,0表示GPT定时器计数值默认为上次关闭的时候值,为1表示默认值为0

bit 2

GPT Debug Enable: 调试模式使能

bit 3

GPT Wait Mode Enable: 等待模式使能

bit 4

GPT Doze Mode Enable: 休眠模式使能

bit 5

GPT Stop Mode Enable: 停止模式使能

bits 6-8

GPT Clock Source: 时钟源选择

000: 时钟源关闭001: 使用IPG时钟源010: 使用高频IPG时钟源011: 使用外部时钟源100: 使用外设时钟源101: 使用晶体振荡器作为参考时钟,频率为24 MHzbit 9

GPT Free-Run or Restart Mode: 自由运行或重启模式,0为Restart 模式, 1为 Free-Run模式。

bit 10

EN_24M: 使能24 MHz晶体振荡器输入时钟。

硬件复位会重置EN_24M位。软件复位不会影响EN_24M位。bit 11-14

未使用

bit 15

SWR: 软件复位,这是GPT模块的软件复位位。它是一个自清除位。

当模块处于复位状态时,SWR位被置位。当复位过程完成时,SWR位被清除。设置SWR位会将所有寄存器重置为默认复位值,除了GPT控制寄存器中的EN、ENMOD、STOPEN、WAITEN和DBGEN位。0: GPT不处于复位状态1: GPT处于复位状态bit22-20 OM1, bit25-23 OM2, bit 28-26 OM3

设置比较输出功能,比较事件发生以后,相应的IO输出:

000: 输出断开。引脚上无响应。001: 切换输出引脚,翻转输出;010: 清除输出引脚,清0。011: 设置输出引脚,置1。
1xx: 在输出引脚上生成一个有效低脉冲(即一个输入时钟宽度)。在比较事件发生时,输出引脚立即设置为1,并在下一个输入时钟时生成一个低脉冲。bit 29 FO1, bit30 FO2, bit31 FO3

强制输出比较通道3

0: 写0无效。1: 在定时器输出比较通道3引脚上执行编程的引脚操作;OF3标志不设置。

本文实验使用 IPG时钟源, Restart Mode。

用来设置分频值。
bits 0-11: 分频值(Prescaler Value)
这些位用于设置预分频值。预分频值的范围通常为0到4095。
实际的分频因子为(分频值 + 1),即如果分频值为0,则分频因子为1;如果分频值为1,则分频因子为2,以此类推。

这个用来设置 Crystal Oscillator 24M 的分频。

GPTx_SR(Status Register)是GPT的状态寄存器,用于指示定时器的各种状态和事件。功能位的作用如下:

GPTx_IR(Interrupt Register)是GPT的中断寄存器,用于配置和控制定时器的中断功能,各位作用如下:

bit 0: Output Compare 1 Interrupt Enable (OF1IE)0: 禁用输出比较通道1中断1: 使能输出比较通道1中断bit 1: Output Compare 2 Interrupt Enable (OF2IE)0: 禁用输出比较通道2中断1: 使能输出比较通道2中断bit 2: Output Compare 3 Interrupt Enable (OF3IE)0: 禁用输出比较通道3中断1: 使能输出比较通道3中断bit 3: Input Capture 1 Interrupt Enable (IF1IE)0: 禁用输入捕获通道1中断1: 使能输入捕获通道1中断bit 4: Input Capture 2 Interrupt Enable (IF2IE)0: 禁用输入捕获通道2中断1: 使能输入捕获通道2中断bit 5: Rollover Interrupt Enable (ROVIE)0: 禁用溢出中断1: 使能溢出中断

在 bsp_delay.c 里实现下面功能。

/*** @brief 初始化GPT定时器*/void gpt1_timer_init(void){// bit0 软复位GPT1->CR = 0;GPT1->CR = 1 SR & (1 CR |= (1 CR |= (1 CR &= ~(1 PR = 65;// 设置输出比较寄存器1的值,设置为1000000,即500msGPT1->OCR[0] = TIMER_DURATION;// bit0 使能输出比较中断GPT1->IR = (1 CR |= (1 /*** @brief GPT中断服务函数*/void gpt1_timer_irqhandler(unsigned int gicciar, void *param){static unsigned char state = 0;if(GPT1->SR & (1 SR |= (1

上面代码段里,

// bit0 软复位GPT1->CR = 0;GPT1->CR = 1 SR & (1 CR |= (1 CR |= (1 CR &= ~(1 PR = 65;

这里实现了1MHz的时钟设置,即每个计数是1uS,只要计算 GPT1->CNT 数值即可。

/*** @brief 延时us*/void delay_us(unsigned int us){unsigned long old_cnt;unsigned long tcntvalue = 0;old_cnt = GPT1->CNT;while(1){unsigned long new_cnt = GPT1->CNT;if(new_cnt != old_cnt){if(new_cnt > old_cnt){tcntvalue += new_cnt - old_cnt;}else{tcntvalue += 0xffffffff - old_cnt + new_cnt;}}if(tcntvalue >= us){break;}}}/*** @brief 延时ms*/void delay_ms(unsigned int ms){while(ms--){delay_us(1000);}}

main 函数:

#include "inc/main.h"#include "bsp_clk.h"#include "bsp_delay.h"#include "led.h"#include "beep.h"#include "key.h"#include "bsp_int.h"//#include "bsp_exti.h"#include "bsp_epit.h"#include "bsp_keyfilter.h"int main(void){bsp_int_init; /* 初始化中断 */imx6u_clkinit; /* 初始化系统时钟 */clk_enable; /* 使能外设时钟 */led_init; /* 初始化LED */beep_init; /* 初始化蜂鸣器 */// exti_init; /* 初始化外部中断 */// epit_init(EPIT1, 0, 66000000 / 2); /* 初始化EPIT1, 1分频, 500ms中断一次 */// keyfilter_init; /* 初始化按键 */// gpt1_timer_init; /* 初始化GPT1定时器 */gpt1_delay_init; /* 初始化GPT1高精度延时 */while(1) {delay_ms(500);led_switch(LED0, 0);delay_ms(500);led_switch(LED0, 1);}return 0;}

本文代码开源地址;

来源:编程圈子

相关推荐