ARM嵌入式学习--第七天(GPT)

发布于:2024-12-20 ⋅ 阅读:(13) ⋅ 点赞:(0)

GPT

-介绍

    GPT有一个32位向上计数器,定时计数器值可以使用外部引脚上的事件捕获到寄存器中,捕获触发器可以被编程为上升沿和下降沿。GPT还可以在输出比较引脚上生成事件,并在定时器达到编程值时产生中断。GPT有一个12位预分频器,它提供从多个时钟源获得的可编程时钟频率

 -特征

    1.一个带时钟源选择的32位向上计数器,包括外部时钟

    2.俩个具有可编程触发边缘的输入捕获通道

    3.三个具有可编程输出模式的输出比较通道还提供强制比较功能

    4.可编程为在低功耗调试模式下处于活动状态

    5.在捕获比较翻转事件时中断生成

    6.为计数器操作重新启动或自由运行模式

-GPT的工作原理

 选择时钟信号

    IMX6ULL有4个时钟源可供GPT选择输入到预分频器,分别为:

        1.高频参考时钟ipg_clk_highfreq

        2.低频参考时钟ipg_clk_32k

        3.外围时钟ipg_clk

        4.外部时钟(GPT_CLK)或者晶体振荡器时钟ipg_clk_24M

        (外部时钟或晶体振荡器只能选择一个)

   这里选择ipg_clk=66MHZ作为GPT定时器的输入时钟源,芯片在启动的时候,芯片内部的程序已经做了系统时钟的初始化

预分频设置寄存器(GPT_PR)

    时钟频率与预分频数的关系最终输入频率=时钟频率/(预分频数+1)

GPT计数器工作模式

    GPT计数器可以编程为以俩种模式之一工作:重新启动模式自由运行模式

    在重新启动模式下(可通过GPT控制寄存器GPT_CR选择),当计数器达到比较值时,计数器复位并从0x000000000再次启动重新启动功能仅与比较通道1相关联

    在自由运行模式下,当所有3个通道发生比较事件时,计数器不会重置;相反,计数器会继续计数,直到0xffffffffff,然后归零

GPT操作

    通用计时器(GPT)有一个计数器GPT_CNT),它是一个32位自由运行的向上计数器,它在软件启用后开始计数EN=1

    tips

        1.如果禁用GPT计时器(EN=0),则主计数器和预分频计数器将冻结其当前计数值ENMOD位确定设置EN位并再次启用计数器时GPT计数器的值

        2.如果设置了ENMOD位=1),则启用GPT时,主计数器和预分频器计数器值将重置为0EN=1

        3.如果ENMOD位被编程为0,则当GPT再次启用时(EN=1),主计数器和预分频器计数器从其冻结值重新开始计数

     软件复位GPT_CR控制寄存器中的SWR)复位除EN,ENMOD,STOPEN,WAITEN和DBGEN位之外的所有寄存器位。这些位的状态不受软件复位的影响禁用GPT时,可以进行软件复位

-GPT的输入捕获

使用场景

    在嵌入式开发中,经常需要捕获传感器的高电平(或低电平)信号的持续时间,如红外解码信号,编码器输入信号等

    直观的理解,就是要不断的检测这个信号,当信号从0变成1时,记录一个时间time1,再从1变成0时,记录另一个时间time2俩个时间差就是高电平的持续时间(time2-time1)

工作原理

1.启动定时器,让CNT计数器在不停的计数

2.首先配置定时器的输入通道为上升沿捕获,这样当检测到从0到1的跳变时,ICR捕获寄存器)就会先保存当前的CNT值

3.然后将定时器的输入通道为下降沿捕获,当检测到从1到0的跳变时,ICR就会保存当前的CNT值

4.最终根据俩次捕获的值,就可以计算出高电平持续时间

    tips:

        IMX6ull芯片有俩个GPT定时器

-GPT的输出比较

工作原理

    有三个输出比较通道,它们使用相同的计数器(GPT_CNT)作为输入捕获通道。当输出比较寄存器的编程内容与GPT_CNT中的值匹配设置输出比较状态标志并生成中断

(还有一个“强制比较”(forced-compare)功能,一但设置,就会马上产生比较事件,不管当前计数器的值是否等于比较值,强制比较的产生的事件,跟正常的输出事件相同,只是它不会设置状态标记位并且不会产生中断,一旦设置force-compare位,该事件就会即刻产生,这个位是自动清除的)

-高精度延时实现

实现思路

1.软件复位GPT定时器

2.确定GPT定时器的时钟源

3.预分频器的设置

4.确定比较寄存器的值(根据延时时间来确定

5.开启GPT定时器

6.等待输出比较事件的产生

7.关闭GPT定时器

代码实现
gpt.c
#include "gpt.h"

//初始化
void gpt_int(){
//停止gpt
    GPT1->CR &= ~(0x1<<0);
//软件复位gpt
    GPT1->CR |= (0x1<<15);
//等待复位状态
    while(GPT1->CR & (0x1<<15));
//时钟源选择
    GPT1->CR &= ~(0x7<<6);
    GPT1->CR |=(0X1<<6);
}

//预分频器设置
void gpt_divide(){
    GPT1->PR &= ~(0xfff<<0);
    GPT1->PR |= (0x41<<0);
}


//开始GPT
void gpt_start(){
//设置ENMOD
    GPT1->CR |= (0x1<<1);
//设置工作模式FRR
    GPT1->CR |=(0x1<<9);
//使能gpt
    GPT1->CR |= (0x1<<0);
}

//关闭GPT
void gpt_stop(){
    GPT1->CR &= ~(0x1<<0);
}


//设置比较寄存器的值
void gpt_compare(int value){
    GPT1->OCR3 = value;
}

//等待比较事件的发生
void gpt_wait_compare(){
    while(!(GPT1->SR & (0x1<<2)));
}

void gpt_delay_useconds(int value){
    gpt_int();
    gpt_divide();
    gpt_compare(value);
    gpt_start();
    gpt_wait_compare();
    gpt_stop();
}

void gpt_delay_mseconds(int value){
    gpt_int();
    gpt_divide();
    gpt_compare(value*1000);
    gpt_start();
    gpt_wait_compare();
    gpt_stop();
}

void gpt_delay_seconds(int value){
    gpt_int();
    gpt_divide();
    gpt_compare(value*1000*1000);
    gpt_start();
    gpt_wait_compare();
    gpt_stop();
}

gpt.h
#ifndef __GPT_HEAD__
#define __GPT_HEAD__


#include "../../include/imx6ull.h"
#include <stdio.h>


extern void gpt_delay_seconds(int value);
extern void gpt_delay_mseconds(int value);
extern void gpt_delay_useconds(int value);
#endif