I.MX6U 裸机开发18.GPT定时器实现高精度延时

I.MX6U 裸机开发18.GPT定时器实现高精度延时

  • 一、GPT定时器简介
    • 1. GPT 功能
    • 2. 时钟源
    • 3. 框图
    • 4. 运行模式
      • (1)Restart mode
      • (2)Free-Run Mode
    • 5. 中断类型
      • (1)溢出中断 Rollover Interrupt
      • (2)输入捕获中断 Input Capture Interrupt 1,2
      • (3)输出捕获中断 Output Compare Interrupt 1,2,3
    • 6. 寄存器
      • (1) GPTx_CR
        • bit 0
        • bit 1
        • bit 2
        • bit 3
        • bit 4
        • bit 5
        • bits 6-8
        • bit 9
        • bit 10
        • bit 11-14
        • bit 15
        • bit22-20 OM1, bit25-23 OM2, bit 28-26 OM3
        • bit 29 FO1, bit30 FO2, bit31 FO3
      • (2) GPTx_PR 分频寄存器
      • (3) GPTx_SR 状态寄存器
        • **bit 0**: Output Compare 1 Flag (OF1)
        • **bit 1**: Output Compare 2 Flag (OF2)
        • **bit 2**: Output Compare 3 Flag (OF3)
        • **bit 3**: Input Capture 1 Flag (IF1)
        • **bit 4**: Input Capture 2 Flag (IF2)
        • **bit 5**: Rollover Flag (ROV)
      • (4) GPTx_IR 中断寄存器
      • GPTx_IR 中断寄存器
  • 二、定时器中断实现500ms定时
    • 1. 初始化 GPT 定时器
    • 2. 中断函数里实现LED闪烁
  • 三、实现高精度延时
    • 1. 实现高精度延时的做法
    • 2. 实现us延时
    • 3. 实现 ms 延时

一、GPT定时器简介

1. GPT 功能

IMX6ULL 的GPT定时器(General Purpose Timer)是一种通用定时器,可以用于生成精确的时间延迟、测量时间间隔、产生周期性中断等,以下是它的几个特性:

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

相比较,EPIT:

  • 32位向下计数器
  • 没有捕获功能

2. 时钟源

在这里插入图片描述
本文使用 ipg_clk 作为时钟源,即66MHz。

3. 框图

在这里插入图片描述

  1. 从左上角开始,输入时钟
  2. 时钟进入 Prescaler 12位分频器(值0~4095)
  3. 分频后进入 Timer Counter,即32位计数器
  4. GET_CAPTURE1, GET_CAPTURE2 实现捕获功能
  5. TIMER Output Reg1~3, 是三路时钟输出,Timer Count要与这三路值进行比较,
  6. GET_COMPARE1~3,三路比较输出

4. 运行模式

(1)Restart mode

自由运行模式,计数器从零开始计数,并在达到最大值后回到零,继续计数。这个模式通常用于测量时间间隔或生成周期性中断。
比较的时候,是比较定时器的计数值和比较寄存器OCR。

特点:

  1. 计数器不断循环计数。
  2. 可以配置中断,在计数器溢出时触发中断。
  3. 只有比较通道1适用这种模式。

(2)Free-Run Mode

输入捕获模式,计数器在检测到外部事件(如信号边沿)时捕获当前计数值,并将其存储在捕获寄存器中。这个模式通常用于测量外部事件的时间间隔。

特点:

  1. 计数器在检测到外部事件时捕获当前计数值。
  2. 可以配置中断,在捕获事件发生时触发中断。
  3. 三个通道都适用, 从0开始一直加到 0xFFFFFFFF,然后重新从0开始。

5. 中断类型

(1)溢出中断 Rollover Interrupt

计数器达到其最大值并回到零时,会触发溢出中断。这个中断通常用于周期性任务或需要精确时间间隔的应用。

(2)输入捕获中断 Input Capture Interrupt 1,2

可以捕获外部事件的时间戳。GPT有两个输入捕获通道,分别为输入捕获中断1(Input Capture Interrupt 1)和输入捕获中断2(Input Capture Interrupt 2)。

(3)输出捕获中断 Output Compare Interrupt 1,2,3

在计数器达到预设值时触发中断。GPT有三个输出比较通道,分别为输出比较中断1(Output Compare Interrupt 1)、输出比较中断2(Output Compare Interrupt 2)和输出比较中断3(Output Compare Interrupt 3)。

6. 寄存器

(1) GPTx_CR

GPTx_CR 是 GPT的控制寄存器,用于配置和控制 GPT 定时器的各种功能。以下是 GPTx_CR 寄存器的各个功能位的详细说明:

bit 0

GPT Enable: 使能GPT定时器,1使能

bit 1

GPT Enable Mode: 使能模式,0表示GPT定时器计数值默认为上次关闭的时候值,为1表示默认值为0

bit 2

GPT Debug Enable: 调试模式使能

bit 3

GPT Wait Mode Enable: 等待模式使能

bit 4

GPT Doze Mode Enable: 休眠模式使能

bit 5

GPT Stop Mode Enable: 停止模式使能

bits 6-8

GPT Clock Source: 时钟源选择

  • 000: 时钟源关闭
  • 001: 使用IPG时钟源
  • 010: 使用高频IPG时钟源
  • 011: 使用外部时钟源
  • 100: 使用外设时钟源
  • 101: 使用晶体振荡器作为参考时钟,频率为24 MHz
bit 9

GPT Free-Run or Restart Mode: 自由运行或重启模式,0为Restart 模式, 1为 Free-Run模式。

bit 10

EN_24M: 使能24 MHz晶体振荡器输入时钟。

  • 硬件复位会重置EN_24M位。
  • 软件复位不会影响EN_24M位。
bit 11-14

未使用

bit 15

SWR: 软件复位,这是GPT模块的软件复位位。它是一个自清除位。

  • 当模块处于复位状态时,SWR位被置位。
  • 当复位过程完成时,SWR位被清除。
  • 设置SWR位会将所有寄存器重置为默认复位值,除了GPT控制寄存器中的EN、ENMOD、STOPEN、WAITEN和DBGEN位。
    • 0: GPT不处于复位状态
    • 1: GPT处于复位状态
bit22-20 OM1, bit25-23 OM2, bit 28-26 OM3

设置比较输出功能,比较事件发生以后,相应的IO输出:

  • 000: 输出断开。引脚上无响应。
  • 001: 切换输出引脚,翻转输出;
  • 010: 清除输出引脚,清0。
  • 011: 设置输出引脚,置1。
    1xx: 在输出引脚上生成一个有效低脉冲(即一个输入时钟宽度)。在比较事件发生时,输出引脚立即设置为1,并在下一个输入时钟时生成一个低脉冲。
bit 29 FO1, bit30 FO2, bit31 FO3

强制输出比较通道3

  • 0: 写0无效。
  • 1: 在定时器输出比较通道3引脚上执行编程的引脚操作;OF3标志不设置。

本文实验使用 IPG时钟源, Restart Mode。

(2) GPTx_PR 分频寄存器

用来设置分频值。
bits 0-11: 分频值(Prescaler Value)
这些位用于设置预分频值。预分频值的范围通常为0到4095。
实际的分频因子为(分频值 + 1),即如果分频值为0,则分频因子为1;如果分频值为1,则分频因子为2,以此类推。

这个用来设置 Crystal Oscillator 24M 的分频。

(3) GPTx_SR 状态寄存器

GPTx_SR(Status Register)是GPT的状态寄存器,用于指示定时器的各种状态和事件。功能位的作用如下:

bit 0: Output Compare 1 Flag (OF1)
  • 当输出比较通道1发生比较事件时,该位被置位。
  • 0: 没有发生比较事件
  • 1: 发生了比较事件
bit 1: Output Compare 2 Flag (OF2)
  • 当输出比较通道2发生比较事件时,该位被置位。
  • 0: 没有发生比较事件
  • 1: 发生了比较事件
bit 2: Output Compare 3 Flag (OF3)
  • 当输出比较通道3发生比较事件时,该位被置位。
  • 0: 没有发生比较事件
  • 1: 发生了比较事件
bit 3: Input Capture 1 Flag (IF1)
  • 当输入捕获通道1发生捕获事件时,该位被置位。
  • 0: 没有发生捕获事件
  • 1: 发生了捕获事件
bit 4: Input Capture 2 Flag (IF2)
  • 当输入捕获通道2发生捕获事件时,该位被置位。
  • 0: 没有发生捕获事件
  • 1: 发生了捕获事件
bit 5: Rollover Flag (ROV)
  • 当计数器发生溢出时,该位被置位。
  • 0: 没有发生溢出
  • 1: 发生了溢出

(4) GPTx_IR 中断寄存器

GPTx_IR 中断寄存器

GPTx_IR(Interrupt Register)是GPT的中断寄存器,用于配置和控制定时器的中断功能,各位作用如下:

  • bit 0: Output Compare 1 Interrupt Enable (OF1IE)

    • 0: 禁用输出比较通道1中断
    • 1: 使能输出比较通道1中断
  • bit 1: Output Compare 2 Interrupt Enable (OF2IE)

    • 0: 禁用输出比较通道2中断
    • 1: 使能输出比较通道2中断
  • bit 2: Output Compare 3 Interrupt Enable (OF3IE)

    • 0: 禁用输出比较通道3中断
    • 1: 使能输出比较通道3中断
  • bit 3: Input Capture 1 Interrupt Enable (IF1IE)

    • 0: 禁用输入捕获通道1中断
    • 1: 使能输入捕获通道1中断
  • bit 4: Input Capture 2 Interrupt Enable (IF2IE)

    • 0: 禁用输入捕获通道2中断
    • 1: 使能输入捕获通道2中断
  • bit 5: Rollover Interrupt Enable (ROVIE)

    • 0: 禁用溢出中断
    • 1: 使能溢出中断

二、定时器中断实现500ms定时

在 bsp_delay.c 里实现下面功能。

1. 初始化 GPT 定时器


/**
 * @brief 初始化GPT定时器
 */
void gpt1_timer_init(void)
{
    // bit0 软复位
    GPT1->CR = 0;
    GPT1->CR = 1 << 15;
    while(GPT1->SR & (1 << 15));

    // bit1, GPT 定时器计数器的初始值,为1表示默认值为0,0表示为上次关闭时候的值
    GPT1->CR |= (1 << 1);

    // bit6~8 时钟源,001表示ipg_clk
    GPT1->CR |= (1 << 6);

    // bit9 运行模式,设置为Restart模式(默认就是0,也可以不设置)
    GPT1->CR &= ~(1 << 9);

    // 设置分频值,使用PR寄存器,设置为66分频,这样进入GPT1的时钟为66MHz/66=1MHz
    GPT1->PR = 65;

    // 设置输出比较寄存器1的值,设置为1000000,即500ms
    GPT1->OCR[0] = TIMER_DURATION;

    // bit0 使能输出比较中断
    GPT1->IR = (1 << 0);

    // 设置GIC中断
    GIC_EnableIRQ(GPT1_IRQn);

    // 注册中断服务函数
    sys_irq_handle_register(GPT1_IRQn, (system_irq_handler_t)gpt1_timer_irqhandler, NULL);

    // 使能GPT1定时器
    GPT1->CR |= (1 << 0);
}

2. 中断函数里实现LED闪烁


/**
 * @brief GPT中断服务函数
 */
void gpt1_timer_irqhandler(unsigned int gicciar, void *param)
{
    static unsigned char state = 0;
    if(GPT1->SR & (1 << 0)) {
        state = !state;
        led_switch(LED0, state);
    }
    // 清除中断标志位
    GPT1->SR |= (1 << 0);
}

三、实现高精度延时

1. 实现高精度延时的做法

上面代码段里,

    // bit0 软复位
    GPT1->CR = 0;
    GPT1->CR = 1 << 15;
    while(GPT1->SR & (1 << 15));

    // bit1, GPT 定时器计数器的初始值,为1表示默认值为0,0表示为上次关闭时候的值
    GPT1->CR |= (1 << 1);

    // bit6~8 时钟源,001表示ipg_clk
    GPT1->CR |= (1 << 6);

    // bit9 运行模式,设置为Restart模式(默认就是0,也可以不设置)
    GPT1->CR &= ~(1 << 9);

    // 设置分频值,使用PR寄存器,设置为66分频,这样进入GPT1的时钟为66MHz/66=1MHz
    GPT1->PR = 65;

这里实现了1MHz的时钟设置,即每个计数是1uS,只要计算 GPT1->CNT 数值即可。

2. 实现us延时

/**
* @brief 延时us
*/
void delay_us(unsigned int us){
    unsigned long old_cnt;
    unsigned long tcntvalue = 0;

    old_cnt = GPT1->CNT;
    while(1){
        unsigned long new_cnt = GPT1->CNT;
        if(new_cnt != old_cnt){
            if(new_cnt > old_cnt){
                tcntvalue += new_cnt - old_cnt;
            }else{
                tcntvalue += 0xffffffff - old_cnt + new_cnt;
            }
        }
        if(tcntvalue >= us){
            break;
        }
    }
}

3. 实现 ms 延时

/**
* @brief 延时ms
*/
void delay_ms(unsigned int ms){
    while(ms--){
        delay_us(1000);
    }
}

main 函数:

#include "inc/main.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "bsp_int.h"
//#include "bsp_exti.h"
#include "bsp_epit.h"
#include "bsp_keyfilter.h"

int main(void)
{
    bsp_int_init();  /* 初始化中断 */
    imx6u_clkinit();    /* 初始化系统时钟 */
    clk_enable();   /* 使能外设时钟 */
    led_init();     /* 初始化LED */
    beep_init();    /* 初始化蜂鸣器 */
//    exti_init();    /* 初始化外部中断 */
//    epit_init(EPIT1, 0, 66000000 / 2);  /* 初始化EPIT1, 1分频, 500ms中断一次 */
//    keyfilter_init();   /* 初始化按键 */
//    gpt1_timer_init();  /* 初始化GPT1定时器 */
    gpt1_delay_init();  /* 初始化GPT1高精度延时 */
    while(1) {
        delay_ms(500);
        led_switch(LED0, 0);
        delay_ms(500);
        led_switch(LED0, 1);
    }
    return 0;
}

本文代码开源地址;
https://gitee.com/xundh/learn_i.mx6u.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921508.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊IP关联是什么?我们该怎么解决呢?

亚马逊不仅提供了广泛的商品和服务&#xff0c;也是许多企业和个人选择的电子商务平台。然而&#xff0c;与亚马逊相关的IP关联问题&#xff0c;特别是在网络安全和运营管理方面&#xff0c;经常成为使用亚马逊服务的用户和商家关注的焦点。通过了解亚马逊IP关联的含义、可能的…

摄影:相机控色

摄影&#xff1a;相机控色 白平衡&#xff08;White Balance&#xff09;白平衡的作用&#xff1a; 白平衡的使用环境色温下相机色温下总结 白平衡偏移与包围白平衡包围 影调 白平衡&#xff08;White Balance&#xff09; 人眼看到的白色&#xff1a;会自动适应环境光线。 相…

Python模块、迭代器与正则表达式day10

1、Python模块 1.1模块的简介 在编写代码的时候&#xff0c;创建的.py文件就被称为一个模块 1.2模块的使用 想要在a文件里使用b文件的时候&#xff0c;只要在a文件中使用关键字import导入即可 1.2.2 from ...import...语句 导入模块可以使用import&#xff0c;如果只导入模…

鸿蒙系统下使用AVPlay播放视频,封装播放器

鸿蒙系统下使用AVPlay开发一款视频播放器流程 一. 申请权限 申请相关权限&#xff0c;主要是读取存储卡权限&#xff0c;方便后面扫描视频用&#xff1a; getPermission(): void {let array: Array<Permissions> [ohos.permission.WRITE_DOCUMENT,ohos.permission.REA…

城电科技|太阳能折叠灯:点亮你的便捷之光

朋友们&#xff0c;今天要给你们介绍一款能让生活变得更加美好的神器 —— 太阳能折叠灯&#xff01; 【超便捷折叠设计】 它就像一个百变精灵&#xff0c;轻松折叠起来后小巧玲珑。可以随意塞进背包的缝隙&#xff0c;或者放在车载储物箱里&#xff0c;完全不占地方&#xff…

二次封装的天气时间日历选择组件

这个接口没调通 没有数据展示~ userStore.badgeDate是VUEX全部存的日历数据 <template><!-- 日历组件 --><el-date-pickerref"elPicker":size"size"v-model"dateTimeValue":type"dateType":range-separator"rang…

PLC与PLC跨网段通讯的几种方法:厂区组网实践

PLC通常通过以太网或其他工业网络协议&#xff08;如PROFINET、Modbus TCP等&#xff09;进行通信。当PLC位于不同的网段时&#xff0c;它们不能直接通信&#xff0c;需要特殊的配置或设备来实现通信&#xff0c;不同网段的PLC通讯变得尤为重要。 随着工业网络的发展和工业4.0概…

常见的上网方式:PPPoE、静态IP、动态IP地址

常见的上网方式有&#xff1a;PPPoE、静态IP、动态IP地址三种。本文给予简单的介绍&#xff1a; 1.PPPoE PPPoE也叫宽带拨号上网&#xff0c;拨号宽带接入是当前最广泛的宽带接入方式&#xff0c;运营商分配宽带用户名和密码&#xff0c;通过用户名和密码进行用户身份认证。如…

elasticsearch介绍和部署

1 elasticsearch介绍 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。可以很方便的使大量数据具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸缩性。Elasticsearch 的实现原理主要分为以下几个步骤&#xff0c;首先用户将数据提交到Elasticsea…

在SpringBoot项目中集成MongoDB

文章目录 1. 准备工作2. 在SpringBoot项目中集成MongoDB2.1 引入依赖2.2 编写配置文件2.3 实体类 3. 测试4. 文档操作4.1 插入操作4.1.1 单次插入4.1.2 批量插入 4.2 查询操作4.2.1 根据id查询4.2.2 根据特定条件查询4.2.3 正则查询4.2.4 查询所有文档4.2.5 排序后返回 4.3 删除…

Linux相关概念和易错知识点(21)(软硬链接、动静态库)

目录 1.软硬链接 &#xff08;1&#xff09;软链接 &#xff08;2&#xff09;硬链接 ①实现方式及其功能 ②硬链接在目录中的运用 ③计算子目录数量 2.动静态库 &#xff08;1&#xff09;动态库 ①动态链接和静态链接 ②动态库的实现 ③系统查找动态库问题 ④解决…

Leetcode 组合

使用回溯来解决此问题。 提供的代码使用了回溯法&#xff08;Backtracking&#xff09;&#xff0c;这是一种通过递归探索所有可能解的算法思想。以下是对算法思想的详细解释&#xff1a; 核心思想&#xff1a; 回溯法通过以下步骤解决问题&#xff1a; 路径选择&#xff1a…

工具学习_Docker

0. Docker 简介 Docker 是一个开源平台&#xff0c;旨在帮助开发者构建、运行和交付应用程序。它通过容器化技术将应用程序及其所有依赖项打包在一个标准化的单元&#xff08;即容器&#xff09;中&#xff0c;使得应用程序在任何环境中都能保持一致的运行效果。Docker 提供了…

【从零开始的LeetCode-算法】3233. 统计不是特殊数字的数字数量

给你两个 正整数 l 和 r。对于任何数字 x&#xff0c;x 的所有正因数&#xff08;除了 x 本身&#xff09;被称为 x 的 真因数。 如果一个数字恰好仅有两个 真因数&#xff0c;则称该数字为 特殊数字。例如&#xff1a; 数字 4 是 特殊数字&#xff0c;因为它的真因数为 1 和…

day06(单片机高级)PCB设计

目录 PCB设计 PCB设计流程 元器件符号设计 原理图设计 元器件封装设计 元器件库使用 PCB设计 目的&#xff1a;学习从画原理图到PCB设计的整个流程 PCB设计流程 元器件符号设计 元器件符号&#xff1a;这是电子元器件的图形表示&#xff0c;用于在原理图中表示特定的元器件。例…

Oracle JDK(通常简称为 JDK)和 OpenJDK区别

Java 的开发和运行时环境主要由两种实现主导&#xff1a;Oracle JDK&#xff08;通常简称为 JDK&#xff09;和 OpenJDK。尽管它们都基于同一个代码库&#xff0c;但在一些关键点上有所区别。以下是详细的对比&#xff1a; 1. 基础代码 Oracle JDK&#xff1a; 基于 OpenJD…

LeetCode 101题集(随时更新)

题集来源&#xff1a;GitHub - changgyhub/leetcode_101: LeetCode 101&#xff1a;力扣刷题指南 使用C完成相关题目&#xff0c;以训练笔试 贪心 采用贪心的策略&#xff0c;保证每次操作都是局部最优的&#xff0c;从而使最后得到的结果是全局最优的。 分配问题 455. 分发饼…

渗透测试笔记——shodan(4)

声明&#xff1a; 学习视频来自B站up主 【泷羽sec】有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&am…

06 —— Webpack优化—压缩过程

css代码提取后想要压缩 —— 使用css-minimizer-webpack-plugin插件 下载 css-minimizer-webpack-plugin 本地软件包 npm install css-minimizer-webpack-plugin --save-dev 配置 webpack.config.js 让webpack拥有该功能 const CssMinimizerPlugin require(css-minimizer-…

【Android】android compat理解

1&#xff0c;前提 即便是在同一手机上安装的不同apk&#xff0c;其编译的apk不同&#xff0c;也会导致行为上的差异。如SDK34有限制后台启动&#xff0c;但如果安装的apk所依赖的sdk是33&#xff0c;则不会表现出此差异。这是如何实现的呢&#xff1f;其实&#xff0c;本质是…