(九)arm裸机开发---高精度延时实验

本节介绍另外一个定时器,GPT定时器。通过GPT定时led灯的亮灭,可以输出到示波器上观察精度。

一、GPT定时器

    GPT(General Purpose Timer)定时器和EPIT相比,GPT功能更加强大,有俩个捕获通道,三个输出比较通道,可以生成捕获中断,比较中断,和溢出中断。GPT定时器是向上计数的。

GTP有俩种运行模式:
1.restart模式:GPT1_CR[9] = 0。只适合与通道一。向上计数到比较事件发生,清零,重新计数。我们使用restart模式。
2.free-run模式:GPT1_CR[9] = 1。适合所有通道。即是比较事件发生,依旧向上继续计数。

GPT1_CR寄存器具体的设置:
1.GPT1_CR[15]=1软复位。
2.GPT1_CR[10]=0 不使用24M时钟。
3.GPT1_CR[9] = 0。使用restart模式。
4.GPT1_CR[8:6] = 001 使用ipg_clk时钟。66M。
5.GPT1_CR[0]=1。时钟使能位。

GPT1_PR寄存器具体的设置:
1.GPT1_PR[11:0]=000~fff。代表1到4096分频。我们设置为66分频,即0x41。

GPT1_OCR1寄存器具体的设置:
1.用于设置通道1的比较寄存器的值的。当定时器累加到这个数时,就会产生比较中断。本例程中我们不使用输出比较中断,所以将其设置为最大。

GPT1_CNT:只读寄存器,用于记录当前的计数值。

二、代码实现

1.高精度延时的原理

我们使用的是66M的时钟,使用的是66的分频,所以每秒1M个计数,通过统计GPT1_CNT计数的个数就可以知道延时的时间的长短。

2.具体代码

#include "bsp_delay.h"

void delay_short(volatile unsigned int n){
    while (n--) {}
}

//大约n ms的延时
void delay(int n){
    while (n--){
        delay_short(0x7ff);
    }
}

/*精确延时初始化*/
void precise_timer_init(){
    GPT1->CR = 0;                   //清零
    GPT1->CR = 1 << 15;             //复位
    while((GPT1->CR >> 15) & 0x1);  //等待复位完成
    GPT1->CR = 1 << 6;              //设置时钟66M
    GPT1->PR = 65;                  //设置66分频
    GPT1->OCR[0] = 0xffffffff;      //设置比价寄存器中的值为最大

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


/*用于比较时钟中断实现精准定时*/
#if 0                             
    GPT1->OCR[0] = 0x500000;        //设置比价寄存器中的值为最大
    GIC_EnableIRQ(GPT1_IRQn);       //使能GIC中的GPT1中断
    /*精确延时的中断处理函数*/
    system_register_irq_handler(GPT1_IRQn, system_prescise_timer_irq_handler, NULL);
    GPT1->IR |= 1 << 0;             //设置中断使能
#endif
}

/*精确延时的中断处理函数*/
void system_prescise_timer_irq_handler(unsigned int gicciar, void *param)
{
    static unsigned char status = 0;
    if (GPT1->SR & 0x1)
    {
        status = !status;
        led_switch(LED0, status);
    }
    
    GPT1->SR |= 1 << 0; //清除中断标志位
}

//us级延迟函数,这个函数实在是太垃圾了,中断不好吗
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;                              /* 跳出 */
        }
    }
}

//ms级延迟函数
void delayms(unsigned int msdelay)
{   int i;
    for(i = 0;i < msdelay;i++){
        delayus(1000);
    }
}

总结

本文实现了俩种定时方案,一种就是数定时计数,一种通过中断实现。和前面的EPIT实现相同的功能主要还是在熟悉imx6uLL芯片的各种外设。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值