I.MX6ULL-GPT实现延时
一,定时器介绍
定时器简单来说,就是设置一个时间,然后开始定时,等定时时间到达设定时间的时候,
则发生一些动作,如:响铃。
二, 基本原理
1,计数功能:GPT 通常是一个 32 位或 16 位的计数器,能够对时钟信号进行计数。它可以配置为向上计数、向下计数或者向上向下同时计数,通过对时钟脉冲的计数来实现定时、测量时间间隔或产生特定的时间延迟等功能。
2,时钟源选择:其时钟输入可以选择内部的 PCLKD 分频后输入,或者选择通过 GTETRGn 引脚输入外部时钟,但不能同时选择两者。不同的时钟源选择可以满足不同的应用需求,例如使用内部时钟可以方便地与系统时钟同步,而外部时钟则可以提供更精确的计时基准或与外部事件同步。
3,内部电路
三, 工作原理
1,选择时钟
输入到预分频器的时钟可以从4个时钟源中选择。下表描述了GPT的时钟源。有关时钟设置、配置和门控信息,请参阅时钟控制器模块(CCM)
可以从 4 个时钟源中选择输入到预分频器的时钟,分别为:
高频参考时钟(ipg_clk_highfreq),
低频参考时钟(ipg_clk_32k),
外围时钟(ipg_clk)
外部时钟(GPT_CLK)或者晶体振荡器时钟(ipg_clk_24M)
外部时钟(GPT_CLK)或者晶体振荡器时钟(ipg_clk_24M)只能选择一个。
这里我们选择
ipg_clk=66MHZ
作为GPT定时器的输入时钟源,
芯片在启动的时候,芯片内部的程序已经做了系统时钟初始化,初始化的时钟频率
如下:
2, 时钟源选择寄存器
时钟源选择寄存器主要用于确定通用定时器(GPT)等相关模块获取时钟信号的来源。它允许系统根据实际需求,从多个可用的时钟源中选择合适的一个,以此来驱动定时器进行计数等操作,进而满足不同应用场景对计时精度、与外部事件同步等方面的要求。
3, 预分频设置寄存器:
简单来说,预分频就是对你选择的时钟源进行分频.假如你选择的主板的频率大概是72MHZ,但是定时一般用不了这么的,就好像,坐小车对电机进行pwm控制,一般只需要20k-30kHZ左右进行,这时候就要进行分频,
4,GPT计数器工作模式
GPT计数器可以编程为以两种模式之一工作:重新启动模式或自由运行模式
1,在重新启动模式下(可通过GPT控制寄存器GPT_CR选择),当计数器达到比较值时,计数器复位并从0x00000000再次启动.
2,重新启动功能仅与比较通道1相关联。对通道1的比较寄存器的任何写访 问都将重置GPT计数器。这样做是为了避免在计数进行时比较值从较高值 更改为较低值时可能丢失比较事件。对于其他两个比较通道,当比较事件 发生时,计数器不会重置。
3,在自由运行模式下,当所有3个通道发生比较事件时,计数器不会重置; 相反,计数器继续计数,直到0xffffffff,然后滚动(到0x00000000)
5,GPT操作
1,通用计时器(GPT)有一个计数器(GPT_CNT),它是一个32位自由运行 的向上计数器,它在软件启用后开始计数(EN=1)。
2,如果禁用GPT计时器(EN=0),则主计数器和预分频计数器将冻结其当前计数值。ENMOD位确定设置EN位并再次启用计数器时GPT计数器的值。
3,如果设置了ENMOD位(=1),则启用GPT时,主计数器和预分频器计数器值将重置为0(EN=1),如果ENMOD位被编程为0,则当GPT再次启用时(EN=1),主计数器和预分
频器计数器从其冻结值重新开始计数。
6, GPT的输入捕获
在嵌入式开发中,
我们经常需要捕获传感器的高电平(或低电平)信号的持续时间
,如红外解码信号、 编码器输入信号等。
1, 输入捕获工作原理
(1),启动定时器,让CNT计数器在不停的计数
(2),首先配置定时器的输入通道为上升沿捕获,这样当检测到从0到1的跳变时,ICR就会先保存当前的CNT值
(3),然后将定时器的输入通道为下降沿捕获,当检测从1到0的跳变时,ICR就会先保存当前的CNT值.
(2),最终我们根据两次捕获的值,就可以计算出高电平持续的时间
2, GPT的输入捕获操作
有两个输入捕获通道,每个输入捕获通道都有一个专用的捕获引脚、捕获寄存器和输入边缘检测/选择逻辑。每个输入捕获功能都有一个关联的状态标志,可以导致处理器发出中断服务请求.
当输入捕获引脚上发生选定的边缘转换时,GPT_CNT的内容将在相应的捕 获寄存器上捕获,并设置适当的中断状态标志。如果设置了相应的使能位 (在中断寄存器中),则可以在检测到转换时生成中断请求。捕获可以编 程为发生在输入引脚的上升沿、下降沿、上升沿和下降沿上,或者可以禁 用捕获。事件与选择运行计数器的时钟同步。只有在先前记录的转换之后 至少一个时钟周期(选择运行计数器的时钟)发生的转换才能保证触发捕 获事件。输入转换的锁定中最多可以有一个时钟周期的不确定性。输入捕 获寄存器可以在任何时候读取,而不会影响它们的值。
三个输出比较通道使用相同的计数器(GPT_CNT)作为输入捕获通道。当 输出比较寄存器的编程内容与GPT_CNT中的值匹配时,设置输出比较状态 标志并生成中断(如果在中断寄存器中设置了相应的位)。因此,输出比 较定时器引脚将被设置、清除、切换、完全不受影响或输出一个低脉冲 (脉冲持续时间为定时器的时钟源的周期).
四,代码案例
#include "gpt.h"
void gpt_init()
{
//gpt失能
GPT1->CR &= ~(0x1<<0);
//复位gpt
GPT1->CR |= (0x1<<15);
while(GPT1->CR & (0x1<<15));
//时钟源设置
GPT1->CR &= ~(0x7<<6);
GPT1->CR |= (0x1<<6);
//预分频设置65 1us
GPT1->PR &= ~(0xfff<<0);
GPT1->PR |= (0x41<<0);
}
void gpt_start()
{
GPT1->CR |= (0x1<<1);
GPT1->CR |= (0x1<<9);
//使能
GPT1->CR |= (0x1<<0);
}
void gpt_stop()
{
//失能
GPT1->CR &= ~(0x1<<0);
}
//比较寄存器的值
void gpt_setval(int val)
{
GPT1->OCR3 = val;
}
void gpt_wait()
{
while(!(GPT1->SR & (0x1<<2)));
}
//us
void delay_us(int us)
{
gpt_init();
gpt_setval(us);
gpt_start();
gpt_wait();
gpt_stop();
}
//ms
void delay_ms(int ms)
{
gpt_init();
gpt_setval(ms*1000);
gpt_start();
gpt_wait();
gpt_stop();
}
//s
void delay_s(int s)
{
gpt_init();
gpt_setval(s*1000*1000);
gpt_start();
gpt_wait();
gpt_stop();
}