GPT(General Purpose Timer) :GPT 定时器是一个32位向上定时器(从 0X00000000 开始向上递增计数), GPT 定时器可以跟一个值进行比较,当计数器值和这个值相等的话就发生比较事件,产生比较中断。GPT 定时器有一个 12 位的分频器,可以对 GPT 定时器的时钟源进行分频,
GPT定时器结构
(1)GPT 定时器的时钟源,可以选择ipg_clk_24M、 GPT_CLK(外部时钟)、ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq。这里选择 ipg_clk(66MHz)为 GPT 的时钟源
(2)12 位分频器,对时钟源进行分频处理,可设置 0~4095
(3)经过分频的时钟源进入到 GPT 定时器内部 32 位计数器
(4),(5)GPT 的两路输入捕获通道,也用来测PWM的周期和占空比
(6)(7)三个输出比较寄存器和三路输出比较中断,当计数器里面的值和输出比较寄存器里面的比较值相等就会触发输出比较中断
GPT 定时器有两种工作模式:重新启动(restart)模式和自由运行(free-run)模式
重新启动(restart)模式:当 GPTx_CR(x=1, 2)寄存器的 FRR 位清零的时候GPT 工作在此模式。在此模式下,当计数值和比较寄存器中的值相等计数值就会清零,然后重新从0X00000000 开始向上计数,只有比较通道 1 才有此模式。向比较通道 1 的比较寄存器写入任何数据都会复位 GPT 计数器。对于其他两路比较通道(通道 2 和 3),当发生比较事件以后不会复位计数器
自由运行(free-run)模式:当 GPTx_CR(x=1, 2)寄存器的 FRR 位置 1 时候GPT 工作在此模式下,此模式适用于所有三个比较通道,当比较事件发生以后并不会复位计数器,而是继续计数,直到计数值为 0XFFFFFFFF,然后重新回滚到 0X00000000
SWR(bit15):复位 GPT 定时器,向此位写 1 就可以复位 GPT 定时器,当 GPT 复位完成以
后此为会自动清零FRR(bit9): 运行模式选择,当此位为 0 的时比较通道 1 工作在重新启动(restart)模式
CLKSRC(bit8:6): GPT 定时器时钟源选择位,为 1 时选择ipg_clk 作为时钟源
ENMOD(bit1): GPT 使能模式,此位为 0 的时候如果关闭 GPT 定时器,计数器寄存器保
存定时器关闭时候的计数值。此位为 1 的时候如果关闭 GPT 定时器,计数器寄存器就会清零EN(bit): GPT 使能位,为 1 的时候使能 GPT 定时器,为 0 的时候关闭 GPT 定时器
GPTx_SR( 状态寄存器 )
ROV(bit5): 回滚标志位,当计数值从 0XFFFFFFFF 回滚到 0X00000000 的时此位置 1
IF2~IF1(bit4:3): 输入捕获标志位,当输入捕获事件发生以后此位置 1,一共有两路输入捕
获通道。如果使用输入捕获中断的话需要在中断处理函数中清除此位OF3~OF1(bit2:0):输出比较中断标志位,当输出比较事件发生以后此位置 1,一共有三路
输出比较通道。如果使用输出比较中断的话需要在中断处理函数中清除此位
GPTx_PR( 分频寄存器 ):低12位有效,12 位分频值,可设置 0~4095,分别对应 1~4096 分频
计数寄存器 GPTx_CNT,该寄存器保存着 GPT 定时器的当前计数值。输出比较寄存器GPTx_OCR,当计数器值和寄存器 GPTx_OCR1 中的值相等就会产生比较事件,如果使能了比较中断的话就会触发相应的中断
使用 GPT 定时器来实现高精度延时。如果设置 GPT 定时器的时钟源为 ipg_clk=66MHz,设置 66 分频,进入 GPT定时器的最终时钟频率是 66/66=1MHz,周期为 1us。GPTx_CNT 是个32 位寄存器,如果时钟为 1MHz, GPTx_CNT 最多可以实现0XFFFFFFFFus=4294967295us
≈4294s≈72min。在72 分钟以后 GPTx_CNT 寄存器就会回滚到 0X00000000,也就是溢出,所以需要在延时函数中要处理溢出的情况
GPT定时器的初始化
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
}
对GPT的CR,OCR,PR寄存器的设置,定时器的周期设置位1us即可。
微秒延时函数:
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; /* 跳出 */
}
}
}
由于GPT的定时周期为1us,所以最大延时0XFFFFFFFFus,所以需要在延时函数中要处理溢出的情况
有了微秒的延时函数,实现毫秒延时函数就很简单
void delayms(unsigned int msdelay)
{
int i = 0;
for(i=0; i
注:此定时器没有重装载值寄存器!!!!