ARM裸机开发:GPT定时器

Posted JeckXu666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARM裸机开发:GPT定时器相关的知识,希望对你有一定的参考价值。

ARM裸机开发:GPT定时器

一、硬件平台:

正点原子I.MX6U阿尔法开发板

二、原理分析

I.MX6U 提供了多种硬件定时器,有些定时器功能强大;本章介绍的 GPT 定时器主要用来实现高精度延时,下面对 GPT原理做个简单的分析:

2.1 GPT定时器简介

GPT 定时器是一个 32 位向上定时器 (也就是从 0X00000000 开始向上递增计数),GPT 定时器可以跟一个值进行比较,当计数器值和这个值相等的话就发生比较事件,产生比较中断

GPT 定时器有一个 12 位的分频器,可以对 GPT 定时器的时钟源进行分频

GPT 定时器特性如下:

① 一个可选时钟源的 32 位向上计数器

② 两个输入捕获通道,可以设置触发方式

③ 三个输出比较通道,可以设置输出模式

④ 可以生成捕获中断、比较中断和溢出中断

⑤ 计数器可以运行在重新启动 (restart) 或(自由运行) free-run 模式

GPT 的时钟源可选 5 个:

这5个时钟源对应如下:

  • ipg_clk_24M
  • GPT_CLK(外部时钟)
  • ipg_clk
  • ipg_clk_32k
  • ipg_clk_highfreq

我们选择 ipg_clk 为 GPT 的时钟源,ipg_clk 为 66MHz

GPT 定时器结构如下:

图中信号走线如下:

  1. 时钟源

  2. 分频器

  3. 定时器计数器

  4. 输入捕获

  5. 输入捕获

  6. 输出比较

  7. 输出比较中断

2.2 GPT有关寄存器

2.2.1 GPT配置寄存器

寄存器结构:

SWR(bit15):复位 GPT 定时器

FRR(bit9):运行模式选择

CLKSRC(bit8:6):GPT 定时器时钟源选择位

ENMOD(bit1):GPT 使能模式

EN(bit0):GPT 使能位

2.2.2 GPT分频寄存器

寄存器结构:

PRESCALER(bit11:0): 12 位分频值

2.2.3 GPT状态寄存器

寄存器结构:

ROV(bit5):回滚标志位

IF2~IF1(bit4:3):输入捕获标志位

OF3~OF1(bit2:0):输出比较中断标志位

2.2.4 GPT计数寄存器

GPTx_CNT 保存着 GPT 定时器的当前计数值

2.3 GPT使用步骤

  • 设置 GPT1 定时器
    先复位再设置具体参数
  • 设置 GPT1 的分频值
    设置寄存器 GPT1_PR 寄存器配置分频值
  • 设置 GPT1 的比较值
    用到比较输出中断时设置
  • 使能 GPT1 定时器
  • 编写延时函数
    编写延时函数进行高精度延时

三、程序编写

GPT 用于高精度延时,所以我们复制上一章的工程,修改其延时文件

bsp_delay.c 文件代码修改如下

#include "bsp_delay.h"
#include "imx6ul.h"
void delay(volatile unsigned int n)

	while(n--)
	
		volatile unsigned int i = 0x7ff;
		while(i--);
	



void delay_init(void)

	GPT1->CR = 0; 					/* 清零,bit0也为0,即停止GPT  			*/
	GPT1->CR = 1 << 15;				/* bit15置1进入软复位 				*/
	while((GPT1->CR >> 15) & 0x01);	/*等待复位完成 						*/
	
	/*
   	 * GPT的CR寄存器,GPT通用设置
   	 * bit22:20	000 输出比较1的输出功能关闭,也就是对应的引脚没反应
     * bit9:    0   Restart模式,当CNT等于OCR1的时候就产生中断
     * bit8:6   001 GPT时钟源选择ipg_clk=66Mhz
     * bit
  	 */
	GPT1->CR = (1<<6);

	/*
     * GPT的PR寄存器,GPT的分频设置
     * bit11:0  设置分频值,设置为0表示1分频,
     *          以此类推,最大可以设置为0XFFF,也就是最大4096分频
	 */
	GPT1->PR = 65;	/* 设置为65,即66分频,因此GPT1时钟为66M/(65+1)=1MHz */

	 /*
      * GPT的OCR1寄存器,GPT的输出比较1比较计数值,
      *	GPT的时钟为1Mz,那么计数器每计一个值就是就是1us。
      * 为了实现较大的计数,我们将比较值设置为最大的0XFFFFFFFF,
      * 这样一次计满就是:0XFFFFFFFFus = 4294967296us = 4295s = 71.5min
      * 也就是说一次计满最多71.5分钟,存在溢出
	  */
	GPT1->OCR[0] = 0XFFFFFFFF;

	GPT1->CR |= 1<<0;			//使能GPT1


void delay_us(volatile unsigned int nus)

	unsigned long oldcnt,newcnt;
	unsigned long tcntvalue = 0;	/* 走过的总时间  */

	oldcnt = GPT1->CNT;
	while(1)
	
		newcnt = GPT1->CNT;
		if(newcnt != oldcnt)
		
			if(newcnt > oldcnt)		/* GPT是向上计数器,并且没有溢出 */
				tcntvalue += newcnt - oldcnt;
			else  					/* 发生溢出    */
				tcntvalue += 0XFFFFFFFF-oldcnt + newcnt;
			oldcnt = newcnt;
			if(tcntvalue >= nus)/* 延时时间到了 */
			break;			 		/*  跳出 */
		
	


void delay_ms(volatile unsigned int nms)

	int i = 0;
	for(i=0; i<nms; i++)
	
		delayus(1000);
	

bsp_delay.h 文件代码修改如下

#ifndef __BSP_DELAY_H
#define __BSP_DELAY_H

void delay(volatile unsigned int n);
void delay_init(void);
void delay_us(volatile unsigned int nus);
void delay_ms(volatile unsigned int nms);

#endif

主函数调用延时函数进行延时

#include "bsp_led.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_exit.h"
#include "bsp_epit.h"
#include "imx6ul.h"
int main(void)

    CLK_INIT();
    int_init();
    BSP_KEY_INIT();
    LED_INIT();
    delay_init();
    while (1)
    
        /* code */
        LED_ON();
        delay_ms(1000);
        LED_OFF();
        delay_ms(1000);
    
    return 0;

四、实验现象

LED 按照 1s 的频率进行翻转

以上是关于ARM裸机开发:GPT定时器的主要内容,如果未能解决你的问题,请参考以下文章

ARM裸机开发:C语言点亮LED

ARM裸机开发:主频与时钟

ARM裸机开发:串口通信

ARM裸机开发:输入中断

ARM的异常与裸机开发

ARM裸机开发:RAMROMFLASH概念