13. 高精度延时

13. 高精度延时

  • GPT 定时器简介
    • GPT 定时器结构
    • GPT 定时器工作模式
  • GPT 定时器相关寄存器
    • GPTx_CR
    • GPTx_PR
    • GPTx_SR
    • GPTx_CNT
    • GPTx_OCR
  • GPT 配置步骤
  • 程序编写
    • bsp_delay.h
    • bsp_delay.c
    • main

GPT 定时器简介

GPT 定时器是一个 32 位向上定时器,也就是从0x00000000 开始向上递增计数,GPT 定时器也可以跟一个值进行比较,当计数器值和这个值相等的时候就会发生比较时间,产生比较中断。GPT 定时器有一个 12 位的分频器,可以对 GPT 定时器的时钟源进行分频,GPT 定时器特性:

  1. 一个可选时钟源的 32 位向上计数,本次选择 ipg_clk = 66MHz
  2. 两个输入捕获通道,可以设置触发方式
  3. 三个输出比较通道,可以设置输出模式
  4. 可以生成捕获中断、比较中断和溢出中断
  5. 计数器可以运行在重新启动(restart)或自由运行(free-run) 模式
    在这里插入图片描述

GPT 定时器结构

在这里插入图片描述
1. 此部分是 GPT 定时器的时钟源
2. 此部分为 12 位分频器,对时钟源进行分频处理,可设置 0 ~ 4095 分频,分别对应 1 ~ 4096 分频
3. 经过分频的时钟源进入到 GPT 定时器内部 32 位计数器
4. GPT 的两路输入捕获通道
5. GPT 的两路输入捕获通道
6. 此部分为输出比较寄存器,一共有三路输出比较,因此由三个 32 位输出比较寄存器,
7. 此部分为输出比较中断,三路输出比较中断,当计数器里面的值和输出比较寄存器里面的比较值相等就会触发输出比较中断

GPT 定时器工作模式

重新启动模式: 当 GPTx_CR(x=1,2)寄存器的 FRR 位清零的时候 GPT 工作在此模式。在此模式下,当计数值和比较寄存器中的值相等的话计数值就会清零,然后重新从0x00000000 开始向上计数,只有比较通道 1 才有此模式。向比较通道 1 的比较寄存器写入任何数据都会复位 GPT 计数器。对于其他两路比较通道,当发生比较事件以后不会复位计数器
自由运行模式: 当 GPTx_CR 寄存器的 FRR 位置 1 的时候 GPT 工作在此模式下,此模式适用于所有三个比较通道,当比较事件发生以后并不会复位计数器,而是继续计数,直到计数值为 0xFFFFFFFF,然后重新回滚到 0x00000000

GPT 定时器相关寄存器

GPTx_CR

在这里插入图片描述
SWR(bit15): 复位 GPT 定时器,向此位写 1 就可以复位 GPT 定时器,当 GPT 复位完成后会自动清零
FRR(bit9): 运行模式选择,当此位为 0 的时候比较通道 1 工作在重新启动,为 0 的时候三个比较通道均工作在自由运行模式
CLKSRC(bit8:6): GPT 定时器时钟选择位,为 0 的时候关闭时钟源;为 1 的时候选择 ipg_clk 作为时钟源;为 2 的时候选择 ipg_clk_highfrq 为时钟源;为 3 的时候选择外部时钟作为时钟源;为 4 的时候选择 ipg_clk_32k 为时钟源;为 5 的时候选择 ipg_clk_24M 为时钟源
ENMOD(bit1): GPT 使能模式,此位为 0 的时候如果关闭 GPT 定时器,计数器寄存器保存定时器关闭时候的计数值,为 1 的时候如果关闭 GPT 定时器,计数器寄存器就会清零
EN(bit0): GPT 使能位,1 打开 GPT 定时器,0 关闭 GPT 定时器

GPTx_PR

在这里插入图片描述
PRESCALER(bit11:0): 这就是 12 位分频值

GPTx_SR

在这里插入图片描述
ROV(bit5): 回滚标志位,当计数值从 0xFFFFFFFF 回滚到 0x00000000 的时候此位置 1
IF2 ~ IF1(bit4:3): 输入捕获标志位,当输入捕获事件发生以后此位置 1,一共有两路输入捕获通道,如果使用输入捕获中断的话需要在中断处理函数中清除此位
OF3 ~ OF1(bit2:0): 输出比较中断标志位,当输出比较事件发生以后此位置 1,一共有三路输出比较通道。如果使用输出比较中断的话需要在中断处理函数中清除此位

GPTx_CNT

这个寄存器保存着 GPT 定时器的当前计数值

GPTx_OCR

这个寄存器是输出比较寄存器,每个输出比较通道对应一个输出比较寄存器,因此一个 GPT 定时器有三个 OCR 寄存器,他们的作用都是相同的。这时一个 32 位的寄存器,用于存放 32 位的比较值,当计数器值和比较寄存器的值相等就会触发比较事件,如果使能了比较中断就会触发相应的中断

GPT 配置步骤

  1. 设置 GPT1 定时器
    首先设置 GPT1_CR 寄存器的 SWR(bit15) 位来复位 GPT1,然后设置 GPT1_CR 的CLKSRC(bit8:6) 位,选择时钟源为 ipg_clk,设置定时器工作模式
  2. 设置 GPT1 的分频值
  3. 设置 GPT1 的比较值
  4. 使能 GPT1 定时器
  5. 编写延时函数

程序编写

bsp_delay.h

#pragma once#include "imx6ul.h"
void delay_init(void);
void delayus(unsigned    int usdelay);
void delayms(unsigned	 int msdelay);
void delay(volatile unsigned int n);
void gpt1_irqhandler(void);

bsp_delay.c

#include "bsp_delay.h"/** @description	: 延时有关硬件初始化,主要是GPT定时器GPT定时器时钟源选择ipg_clk=66Mhz* @param		: 无* @return 		: 无*/
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定时器中断代码,* 如果想学习GPT定时器的话可以参考一下代码。*/
#if 0/** GPT的PR寄存器,GPT的分频设置* bit11:0  设置分频值,设置为0表示1分频,*          以此类推,最大可以设置为0XFFF,也就是最大4096分频*/GPT1->PR = 65;	//设置为1,即65+1=66分频,因此GPT1时钟为66M/66=1MHz/** GPT的OCR1寄存器,GPT的输出比较1比较计数值,* 当GPT的计数值等于OCR1里面值时候,输出比较1就会发生中断* 这里定时500ms产生中断,因此就应该为1000000/2=500000;*/GPT1->OCR[0] = 500000;/** GPT的IR寄存器,使能通道1的比较中断* bit0: 0 使能输出比较中断*/GPT1->IR |= 1 << 0;/** 使能GIC里面相应的中断,并且注册中断处理函数*/GIC_EnableIRQ(GPT1_IRQn);	//使能GIC中对应的中断system_register_irqhandler(GPT1_IRQn, (system_irq_handler_t)gpt1_irqhandler, NULL);	//注册中断服务函数	
#endif}#if 0
/* 中断处理函数 */
void gpt1_irqhandler(void)
{ static unsigned char state = 0;state = !state;/** GPT的SR寄存器,状态寄存器* bit2: 1 输出比较1发生中断*/if(GPT1->SR & (1<<0)) {led_switch(LED2, state);}GPT1->SR |= 1<<0; /* 清除中断标志位 */
}
#endif/** @description		: 微秒(us)级延时* @param - value	: 需要延时的us数,最大延时0XFFFFFFFFus* @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);}
}/** @description	: 短时间延时函数* @param - n	: 要延时循环次数(空操作循环次数,模式延时)* @return 		: 无*/
void delay_short(volatile unsigned int n)
{while(n--){}
}/** @description	: 延时函数,在396Mhz的主频下* 			  	  延时时间大约为1ms* @param - n	: 要延时的ms数* @return 		: 无*/
void delay(volatile unsigned int n)
{while(n--){delay_short(0x7ff);}
}

main

#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_keyfilter.h"/** @description	: main函数* @param 		: 无* @return 		: 无*/
int main(void)
{unsigned char state = OFF;int_init(); 				/* 初始化中断(一定要最先调用!) */imx6u_clkinit();			/* 初始化系统时钟 			*/delay_init();				/* 初始化延时 			*/clk_enable();				/* 使能所有的时钟 			*/led_init();					/* 初始化led 			*/beep_init();				/* 初始化beep	 		*/while(1)			{	state = !state;led_switch(LED0, state);delayms(500);}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学【Java多态】-- 写高质量代码

多态的实现条件 在java中要实现&#xff0c;必须要满足如下几个条件&#xff0c;缺一不可。 1.必须在继承体系下2.子类必须要对父类中的方法进行重写3.通过父类的引用调用冲写的方法。 想要真正的学好多态需要去学习一些前置知识&#xff0c;那我们直接开始吧&#xff01; …

Day30力扣打卡

打卡记录 最长回文子序列&#xff08;区间DP&#xff09; 链接 class Solution:def longestPalindromeSubseq(self, s: str) -> int:n len(s)f [[0] * n for _ in range(n)]max lambda x, y: x if x > y else yfor i in range(n - 1, -1, -1):f[i][i] 1for j in ra…

Zookeeper概述

ZooKeeper概述 1 分布式应用程序2 分布式应用程序的特点3 Apache ZooKeeper简介4 ZooKeeper客户端 - 服务器架构5 ZooKeeper 分层命名空间6 Zookeeper 工作流7 ZooKeeper 选举机制7.1 ZooKeeper选举概述7.1.1 两种情况分析 7.2 选举实现细节 8 FastLeaderElection&#xff1a;选…

数字媒体技术基础之:常见图片文件格式

在数字图像处理和图形设计领域&#xff0c;了解不同的图片文件格式及其特点是至关重要的。每种格式都有其独特的用途和优势。以下介绍一些最常见的图片文件格式。 JPEG Joint Photographic Experts Group 扩展名&#xff1a;.jpg 或 .jpeg 特点&#xff1a; 1、有损压缩&#x…

二十、泛型(7)

本章概要 动态类型安全泛型异常混型 C 中的混型与接口混合使用装饰器模式与动态代理混合 动态类型安全 因为可以向 Java 5 之前的代码传递泛型集合&#xff0c;所以旧式代码仍旧有可能会破坏你的集合。Java 5 的 java.util.Collections 中有一组便利工具&#xff0c;可以解…

【多样注释】刚入职就崩溃!这段神秘注释让人无法忍受

最近写码写的头晕脑涨&#xff0c;同事听完后给我发来几张神图&#xff0c;我看完当场笑尿&#x1f923;&#xff0c;分享一下&#xff0c;权当博君一笑了。 代码注释图案传送门 1、看到了这个注释&#xff0c;心凉了一半 2、阅读源码的人&#xff0c;心里一定的崩溃的 3、这…

pycharm/vscode 配置black和isort

Pycharm blackd Pycharm中有插件可以实现后台服务运行black&#xff1a;BlackConnect 安装 配置 Pycharm isort pycharm中&#xff0c;isort没有插件&#xff0c;暂使用外部工具实现&#xff0c;外部工具也可添加快捷键实现快捷对文件、文件夹进行format import&#xff1…

觉非科技发布【轻地图高速NOA智驾方案】|地平线,觉非科技,MobileDrive超捷生态协作实现技术落地

11月10日&#xff0c;2023世界新汽车技术合作生态展期间&#xff0c;觉非科技正式发布了基于地平线征程系列以及MobileDrive超捷规控系统的【轻地图高速NOA智驾解决方案】。该方案首次实现了从芯片能力输出、到数据闭环建设、再到规控部署的产业生态链协作与打通&#xff0c;为…

uniapp运行到安卓模拟器一直在“同步手机端程序文件完成“界面解决办法

如果你是用的模拟器是android studio创建的模拟器&#xff0c;那么你需要新创建一个android11 x86架构的模拟器&#xff1a; 创建完成后&#xff0c;启动模拟器&#xff1a; 然后在hbuilder中重新运行到这个模拟器就可以了&#xff1a; 运行结果&#xff1a; 如果你是用安…

【ccf-csp题解】第11次csp认证-第三题-Json查询超详细讲解

此题思路来源于acwing ccfcsp认证辅导课 题目描述 思路分析 此题的难点在于对输入的内容进行解析&#xff0c;题目中说除了保证字符串内容不会有空格存在之外&#xff0c;其它的任意地方都可能出现空格&#xff0c;甚至在某些地方还会出现空行&#xff0c;这样的话&#xff0…

python数据处理作业4:使用numpy数组对象,随机创建4*4的矩阵,并提取其对角元素

每日小语 真理诚然是一个崇高的字眼&#xff0c;然而更是一桩崇高的业绩。如果人的心灵与情感依然健康&#xff0c;则其心潮必将为之激荡不已。——黑格尔 难点&#xff1a;如何创建&#xff1f;取对角元素的函数是什么&#xff1f; gpt代码学习 import numpy as np# 随机创…

arm2 day6

串口实现单个字符的收发 main.c uart4.c uart4.h