文章目录
简述:
全称:General Purpose Timer。
作用:高精度延时
特性:
- 一个可选时钟源的 32 位向上计数器
- 一个12位的分频器
- 两个输入捕获通道,可以设置触发方式
- 三个输出比较通道,可以设置输出模式
- 可以生成捕获中断、比较中断和溢出中断
- 计数器可以运行在重新启动(restart)或(自由运行)free-run 模式
具体描述
时钟源
一共5个时钟源,由GPTx_CR中的CLKSRC(bit8:6):控制:
CLKSRC | 时钟源 |
---|---|
000 | 关闭时钟源 |
001 | ipg_clk |
010 | ipg_clk_highfreq |
011 | ipg_clk_32k |
100 | ip_clk_24M |
定时器结构
各部分意义:
- GPT 定时器的时钟源
- 此部分为 12 位分频器,对时钟源进行分频处理,可设置0~FFF ,分别对应 1~4096 分频。
- 内部32位计数器
- 输入捕获通道
- 输入捕获通道
- 输出比较器(三个)(32bit)
- 输出比较中断,三路输出比较。当计数器里面的值和输出比较寄存器里面的比较值相等就会触发输出比较中断。
工作模式(两种)
重新启动(restart)模式:
- 条件: GPTx_CR(x=1,2)寄存器的FRR位为0
- 具体工作方式: 当计数值和比较寄存器中的值相等的话计数值就会清零,然后重新从 0X00000000 开始向上计数
- 适用范围:只有比较通道一有此模式
**自由运行模式(free-run)模式: **
- 条件:GPTx_CR(x=1,2)寄存器的FRR位置1
- 具体工作方式:当比较事件发生以后并不会复位计数器,而是继续计数,直到计数值为0XFFFFFFFF,然后重新回滚到 0X00000000。
- 适用:三个比较通道都可
重要寄存器
配置寄存器GPTx_CR
结构图如下:
重要位说明:
位 | 描述 |
---|---|
SWR(bit15) | 复位GPT,当为1是可复位GPT定时器,复位后自动清零 |
FRR(bit9) | 运行模式选择,此位为0的时候比较通道1工作在restart模式,为1时,三个比较通道都在free-run模式 |
SWR(bit15) | GPT定时器时钟源选择位,具体功能上文已描述 |
ENMOD(bit1) | GPT使能模式。为0,如关闭GPT定时器,计数器寄存器保存定时器关闭时候的计数值,为1,则计数器寄存器清零 |
EN(bit) | GPT使能位。1,使能;0,关闭。 |
分频寄存器GPTx_PR
PRESCALER(bit11:0),12位分频值,可设置0FFF,对应分频14049
状态寄存器GPTx_SR
重要位:
位 | 描述 |
---|---|
ROV(bit5) | 回滚标志位,free-run模式下,计数值回滚到0X00000000的时候为1 |
IF2~IF1(bit4:3) | 输入捕获标志位,当输入捕获时间发生后此位置1,一共两路 |
OF3~OF1(bit2:0) | 输出比较中断标志位,当输出比较时间发生以后此位为1,一共三路 |
输出比较寄存器GPTx_OCR
共有三个,每个通道都有一个,32bit,用于存放32bit比较值
计数寄存器GPTx_CNY
只读寄存器,32bit。
保持当前计数值
原理分析
如设置时钟源为ipg_clk = 66MHz,设置66分频,进入GPT定时器的最终频率是66/66 = 1MHz,为1us。通过读取GPTx_CNY中的数值就可以知道当前过去的多长时间(最大值约为72min)
流程分析
- 设置GPT定时器
- 设置GPT的分频值
- 设置GPT的比较值
- 使能GPT定时器
- 编写延时函数
功能描述
通过GPT定时器来实现高精度延时
程序实现
delay.c函数:
/***************************
File name: bsp_delay.c
Author: ori
Version: v1.0
Description:延时文件
Others: 无
log: 2021/2/4
***************************/
#include "bsp_delay.h"
/*
* @description : 延时有关硬件初始化
* @param : 无
* @return : 无
*/
void delay_init(void)
{
GPT1->CR = 0; /* 清零,bit0也为0,即停止GPT */
GPT1->CR = 1 << 15; /* bit15置1进入软复位 */
while((GPT1->CR >> 15) & 0x01); /*等待复位完成 */
/*
* GPT时钟源选择ipg_clk=66Mhz
*/
GPT1->CR = (1<<6);
GPT1->PR = 65; /* 设置为65,即66分频 */
/*
* GPT的OCR1寄存器,GPT的输出比较1比较计数值
* 此时为最大计时数
*/
GPT1->OCR[0] = 0XFFFFFFFF;
GPT1->CR |= 1<<0; //使能GPT1
}
/*
* @description : 微秒(us)级延时
* @param - value : 需要延时的us数
* @return : 无
*/
void delayus(unsigned int usdelay)
{
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 >= usdelay)/* 延时时间到了 */
break;
}
}
}
/*
* @description : 毫秒(ms)级延时
* @param - msdelay : 需要延时的ms数
* @return : 无
*/
void delayms(unsigned int msdelay)
{
int i = 0;
for(i=0; i<msdelay; i++)
{
delayus(1000);
}
}
main函数
/***************************
File name: main.c
Author: ori
Version: v1.0
Description: 高精度延时实验练习
Others: 无
log: 2021/2/4
***************************/
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_exit.h"
#include "bsp_epit.h"
/*
* @description : main函数
* @param : 无
* @return : 无
*/
int main(void)
{
int_init(); /* 初始化中断(一定要最先调用!) */
imx6u_clkinit(); /* 初始化系统时钟 */
clk_enable(); /* 使能所有的时钟 */
led_init(); /* 初始化led */
beep_init(); /* 初始化beep */
unsigned char state = OFF;
while(1)
{
state = !state;
led_switch(LED0,state);
delay(500);
}
return 0;
}
编译烧录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LSZGXlk9-1612410111305)(2CAB38EC297649B49A3BB15A2A7CCB25)]
最后
本文多处参考正点原子的课程和资料(特表感谢)以及《i.MX 6UltraLite Applications Processor Reference Manual》,并在此基础上进了扩展和自己的理解,最后自己动手复原例程。