GPT(General Purpose Timer)定时器实现精确定时

一、GPT定时器简述:

GPT(General Purpose Timer),即通用定时器,该定时器有以下特点
(1)、它有一个可选时钟源的32位向上计数器
(2)、两个captrue(输入捕获)通道,可以设置触发方式
(3)、三个输出比较通道,可设置输出模式
(4)、可以生成溢出中断、捕获中断和比较中断
(5)、有restart和free-run两种运行模式。

  • restart模式下只要向比较通道一的寄存器写入任何数据,计数器都会清零复位,重新开始计数,且当计数器与比较通道一的寄存器值相同时,计数器也会清零复位;
  • free-run模式下,三个输出比较通道都适用,当比较事件发生后计数器不会清零复位,而是继续计数,直到0XFFFFFFFF为止,然后清零继续计数。

(6)、GPT定时器所拥有的寄存器如下:

  • GPTx_CR(控制寄存器):
bit 作用
bit[15] 软件复位,写1就会复位GPT定时器,复位完成后此位会自动清零
bit[9] 运行模式选择位,0:比较通道一工作在restart模式;1:三个输出比较通道都工作在free-run模式
bit[8:6] GPT定时器时钟源选择位。0:关闭时钟源;1:选ipg_clk;2:选 ipg_clk_highfreq;3:选外部时钟;4:选ipg_clk_32k;5:选ipg_clk_24M
bit[1] GPT定时器关闭时的操作位。0:关闭定时器时计数器保存关闭时候的计数值;1:关闭定时器时计数器清零
bit[0] GPT定时器使能位。0:关闭GPT定时器;1:使能GPT定时器
  • GPTx_PR(分频寄存器)
bit 作用
bit[11:0] 设置的分频值,可设置数位0 ~ 4096;代表分频值从1 ~ 4096。
  • GPTx_SR(状态寄存器)
bit 作用
bit[5] 翻转标志位,当计数器从0XFFFFFFFF翻转到0X00000000的时候,此位会被置1 ;写1清零
bit[4:3] 分别是输入捕获2和1的输入捕获标志位,有捕获事件发生时,此位会被置1,用作输入捕获中断时需要在中断服务函数中清楚此位,写1清零
bit[2:0] 分别是输出比较通道3、2、1的输出比较中断标志位,当有输出比较事件发生时,此为会被置1,写1清零
  • GPTx_IR(中断使能寄存器)
bit 作用
bit[5] 0:关闭翻转中断;1:使能翻转中断
bit[4:3] 分别是输入捕获2和1的中断使能位,0:关闭中断;1:使能中断
bit[2:0] 分别是输出比较通道3、2、1的中断使能位,0:关闭中断,1:使能中断
  • 另外还有GPTx_OCR(输出比较通道的寄存器)和GPTx_ICR(输入捕获的寄存器)以及计数器GPTx_CNT。

二、高精度定时的实现

1、GPT定时器初始化

(1)GPTx_CR寄存器清零
(2)GPTx_CR寄存器bit15置1,软件复位
(3)等待复位成功
(4)配置GPTx_CR寄存器,如运行模式、时钟源等
(5)配置GPTx_PR分频寄存器,0 ~ 4095
(6)配置比较输出通道一的寄存器值
(7)使能GPT定时器

/*
 *@description		:初始化GPT1定时器
 *@param			:无
 *@return			:无
 */
void gpt1_init(void)
{
	GPT1->CR = 0;	/*清零*/
	GPT1->CR |= (1 << 15);	/*软件复位*/
	while((GPT1->CR >> 15) & 0x01);	/*等待软件复位成功*/
	GPT1->CR |= (1 << 6);	/*
							*运行模式:restart模式
							*时钟源:ipg_clk=66MHz
							*定时器关闭时保留计数值
							*/
	GPT1->PR = (66-1);	/*设置分频器为66分频*/
	GPT1->OCR[0] = 0XFFFFFFFF;	/*设置输出比较通道一的寄存器值*/
	GPT1->CR |= (1 << 0);	/*使能GPT定时器*/
}

2、微秒级延迟函数的具体实现

/*
 *@description		:微秒延时函数,延时时间1us(精确)
 *@param -us		:要延时的us数
 *@return			:无
 */
void delayus(unsigned int us)
{
	unsigned long oldcnt,newcnt;
	unsigned long tcntvalue = 0;	/*记录总的走过的时间*/
	oldcnt = GPT1->CNT;
	while (1)
	{
		newcnt = GPT1->CNT;
		if(newcnt != oldcnt)	/*计数器计数了*/
		{
			if(newcnt > oldcnt)	/*没有溢出*/
				tcntvalue += newcnt - oldcnt;
			else				/*溢出了*/
				tcntvalue += 0XFFFFFFFF +newcnt - oldcnt;
			oldcnt = newcnt;
			if(tcntvalue >= us)	/*延时时间到了*/
				break;	/*跳出while循环*/
		}
	}
}

你可能感兴趣的:(I.MX6ULL学习笔记)