看完这篇文章你就彻底懂啦{保姆级讲解}-----(I.MX6U驱动GPT定时器中断实现高精度延时) 2023.5.19

news2024/10/2 1:33:16

目录

    • 前言
    • 整体文件结构
    • 源码分析(保姆级讲解)
      • 初始化延时函数部分:
      • 微秒(us)级延时部分
      • 毫秒(ms)级延时部分
      • 主函数main部分
    • 编译下载
    • 结束语

前言

在上一讲过程中我们使用了EPIT定时器来实现了定时器中断,从而解决了按键消抖的问题。但是我们会发现一个问题就是延时时间不准,具体延时函数如下所示:

/*
 * @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);
	}
}

由上述代码可知,使用循环来实现的延时函数不准确,误差会很大,虽然使用到延时函数的地方精度要求都不会很严格(要求严格的话就使用硬件定时器了),但是延时函数肯定是越精确越好。这样延时函数就可以使用在某些对时序要求严格的场合。

所以本篇文章就去讨论下如何使用GPT定时器来实现高精度延时。

整体文件结构

在这里插入图片描述

源码分析(保姆级讲解)

初始化延时函数部分:

void delay_init(void)
{
	GPT1->CR = 0; 					

	GPT1->CR = 1 << 15;				
	while((GPT1->CR >> 15) & 0x01);
	

	GPT1->CR = (1<<6);

	GPT1->PR = 65;	

	GPT1->OCR[0] = 0XFFFFFFFF;
	GPT1->CR |= 1<<0;

}

好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写!

GPT1->CR = 0; 	

//该寄存器具体配置如下:

在这里插入图片描述
在这里插入图片描述

清零,bit0也为0,即关闭GPT定时器

GPT1->CR = 1 << 15;				
while((GPT1->CR >> 15) & 0x01);

由上可知,该寄存器的第15位为复位位,当该位为1时代表可以进行软复位

因为当GPT复位完成后,会自动将该位清零,即复位成功后会退出该while循环

GPT1->CR = (1<<6);

我们在研究该寄存器配置之前先看一下GPT定时器的可选时钟源有哪些。

在这里插入图片描述

从上图所示,一共有5个时钟源,分别为ipg_clk_24M、GPT_CLK(外部时钟)、ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq。在本文章中使用ipg_clk作为GPT的时钟源,那我们看一下该时钟源的时钟频率有多大?

该时钟源的时钟频率为66MHz。

具体配置讲解在之前的文章中有讲解:看完这篇文章你就彻底懂啦{保姆级讲解}-----(I.MX6U驱动GPIO中断《包括时钟讲解》) 2023.5.9

并且GPT定时器结构如图所示:

在这里插入图片描述

①、此部分为 GPT 定时器的时钟源,前面已经说过了,选择 ipg_clk 作为 GPT 定时器时钟源。
②、此部分为 12 位分频器,对时钟源进行分频处理,可设置 0~ 4095,分别对应 1~4096 分
频。
③、经过分频的时钟源进入到 GPT 定时器内部 32 位计数器。
④和⑤、这两部分是 GPT 的两路输入捕获通道,在本文章中不讲解 GPT 定时器的输入捕获。
⑥、此部分为输出比较寄存器,一共有三路输出比较,因此有三个输出比较寄存器,输出比较寄存器是 32 位的。
⑦、此部分位输出比较中断,三路输出比较中断,当计数器里面的值和输出比较寄存器里面的比较值相等就会触发输出比较中断。

GPT1->PR = 65;	

该寄存器如下所示:

在这里插入图片描述
在这里插入图片描述
设置分频值,设置为0即代表1分频,以此类推,最大可以设置为 0XFFF,也就是最大 4096 分频。

所以我们设置该寄存器为65,即代表为65+1 = 66分频,即最终GPT时钟为1MHz。

GPT1->OCR[0] = 0XFFFFFFFF;

该寄存器的具体配置如下:

使用了第一个比较寄存器。

在这里插入图片描述
即使用GPT的输出比较1比较计数值。由于之前配置GPT时钟为1MHz,所以相当于计数器每计一个值就是1us。那么为了实现较大的计数,我们将比较值设置为最大的 0XFFFFFFFF,

在这里插入图片描述

这样一次计满就是:0XFFFFFFFFus = 4294967296us = 4295s = 71.5min
也就是说一次计满最多 71.5 分钟,存在溢出。

GPT1->CR |= 1<<0;

该寄存器具体配置如下:

在这里插入图片描述
在这里插入图片描述
即使能GPT定时器。

微秒(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)		
				tcntvalue += newcnt - oldcnt;
			else  					
				tcntvalue += 0XFFFFFFFF-oldcnt + newcnt;
			oldcnt = newcnt;
			if(tcntvalue >= usdelay)
			break;			 	
		}
	}
}

好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写!

void delayus(unsigned int usdelay)

//该函数的参数usdelay主要是表示需要延时的us数,最大延时0XFFFFFFFFus。

unsigned long oldcnt,newcnt;
unsigned long tcntvalue = 0;	

oldcnt代表上一时刻中GPT定时器计数器寄存器中的值。
newcnt代表此时该时刻GPT定时器计数器寄存器中的值。

tcntvalue 代表走过的总时间,用于判断是否达到了传入函数的参数usdelay值。

oldcnt = GPT1->CNT;

在进入计时之前,先记录该时刻GPT定时器计数器寄存器中的值,并且将该值赋值给oldcnt。

newcnt = GPT1->CNT;

进入while循环后,经历了一段时间,用newcnt重新记录过了一段时间GPT定时器计数器寄存器中的值。

if(newcnt > oldcnt)		
	tcntvalue += newcnt - oldcnt;
else  					
	tcntvalue += 0XFFFFFFFF-oldcnt + newcnt;

如果这两个值不一样,则代表已经经过一段时间,则需要更新tcntvalue。

如果newcnt > oldcnt,则代表GPT是向上计数器,并且没有溢出。

如果不符合newcnt > oldcnt,则代表发生了溢出,即需要更新tcntvalue。

在这里插入图片描述

oldcnt = newcnt;

在更新完tcntvalue之后,将newcnt赋值给oldcnt ,为了下一次计算总时间做准备。

if(tcntvalue >= usdelay)
	break;	

如果tcntvalue 大于了我们所设置的usdelay值,则提前退出该函数即可。

毫秒(ms)级延时部分

void delayms(unsigned int msdelay)
{
	int i = 0;
	for(i=0; i<msdelay; i++)
	{
		delayus(1000);
	}
}

1ms = 1000us。

主函数main部分

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;
}

编译下载

程序运行正常的话 LED0会以 500ms 为周期不断的亮、灭闪烁。

在这里插入图片描述

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT与深度学习的完美融合:打造智能化推荐系统新时代

PNN | AutoRec | 推荐算法 NFM | ChatGPT | 深度学习 新技术如ChatGPT、LLM、AIGC等的兴起&#xff0c;使推荐系统拥有更强的学习和预测能力。然而&#xff0c;推荐算法仍然是深度学习推荐系统中不可或缺的关键技术。推荐算法和这些技术应相辅相成&#xff0c;相互补充。推荐…

五大向量数据库入门横评

本文内容节选自 Paxi.ai 文章分享&#xff0c;Paxi.ai是一个基于GPT-4打造的帮助用户快速使用AI的AI工具&#xff0c;对内容感兴趣的朋友可以上他们官网查看。 从OpenAI发布GPT以来&#xff0c;AI尤其以LLM为代表的项目发展迅速&#xff0c;相信大家已经了解到大语言模型的魅力…

apk 作为资源提供 aar 的过程

1&#xff1a;参考&#xff1a;Android将APK项目封装为SDK(AAR) https://blog.csdn.net/weixin_51522235/article/details/128216091 四大点&#xff1a;1: apply plugin:com.android.library 2:去掉&#xff1a;applicationId 3:去掉&#xff1a;applicationVariants.all…

MySQL:触发器、权限管理

一、学习目标 了解什么是触发器掌握创建触发器的方法掌握查看触发器的方法掌握触发器的使用技巧掌握删除触发器的方法熟练掌握使用触发器的方法和技巧了解什么是权限表掌握权限表的用法掌握账户管理的方法掌握权限管理的方法掌握访问控制的方法熟练掌握新建用户的方法和技巧了…

小程序加weui或者TDesign安装

WeUI样式库展示&#xff1a;https://weui.io/ 微信官方WeUI相关文档&#xff1a;https://wechat-miniprogram.github.io/weui/docs/ WeUI-wxss 项目地址&#xff1a;https://github.com/Tencent/weui-wxss 安装 &#xff0c;1.先安装node.js 2.建立或者打开已经有的项目。…

【SolVES 模型】生态系统服务功能社会价值评估(基于多源环境QGIS、PostgreSQL、ArcGIS、Maxent、R语言)

SolVES模型&#xff08;Social Values for Ecosystem Services&#xff09;全称为生态系统服务社会价值模型&#xff0c;是由美国地质勘探局和美国科罗拉多州立大学联合开发的一款地理信息系统应用程序&#xff0c;开发该模型的目的主要是对生态系统服务功能中的社会价值进行空…

敏捷与瀑布:哪种项目管理方法适合你的企业?

​良好的项目管理可以改变企业的工作流&#xff0c;在减少混乱因素的同时注入方向和组织性。 同时&#xff0c;"项目管理 "对每个人来说并不意味着完全相同的事情。在企业及其客户中&#xff0c;最重要的两种项目管理方法是敏捷和瀑布。而这两种风格之间的差异很大&…

Redis是单线程还是多线程?揭开性能之谜!

大家好&#xff0c;我是小米&#xff0c;在这个充满技术乐趣的小天地里&#xff0c;今天我们来探讨一个备受争议的话题——Redis是单线程还是多线程&#xff1f;这个问题一直困扰着Redis的用户&#xff0c;让我们一起揭开性能之谜吧&#xff01; Redis作为一款高性能键值存储系…

交换机故障恢复

通常情况下&#xff0c;可以为交换机设置enable密码来提供安全&#xff0c;在没有enable密码的情况下&#xff0c;无法对交换机修改任何配置&#xff0c;因此&#xff0c;在忘记enable密码的时候&#xff0c;就意味着无法改动交换机信息。但是&#xff0c;如果能够物理上接触到…

实施办公自动化系统需要注意什么?

办公自动化系统的好处很容易理解。几乎每个企业都会欢迎更高的准确性、效率和利润率。办公自动化这个过程似乎势不可挡&#xff0c;那么该如何实现和管理呢&#xff1f; 决定自动化的内容 在实施办公自动化系统之前&#xff0c;企业将需要花时间研究哪些具体的流程需要自动化…

Go语言核心编程-基本数据类型篇

第 3 章 Golang 变量 3.1 为什么需要变量 3.1.1一个程序就是一个世界 3.1.2变量是程序的基本组成单位 不论是使用哪种高级程序语言编写程序,变量都是其程序的基本组成单位&#xff0c;比如一个示意图&#xff1a; func getVal(numl int, num2 int) (int, int) {sum : num1 n…

【数字敏捷性】上海道宁与​SolarWinds为您提供全面的可观察性、IT 服务管理和数据库管理

SolarWinds Platform是 业界先进的统一监控 可观察性和服务管理平台 它是新一代SolarWinds 可观察性解决方案的基础 并提供了我们如何 为客户解决可观察性挑战的架构 网络管理工具 从配置和流量智能到 性能监控和拓扑映射 可以轻松查看、理解和解决问题 一种集成的多…

【数据结构】--单链表力扣面试题②反转链表

目录 法一&#xff1a;直接反转法 法二&#xff1a;头插法 题述&#xff1a;给你单链表的头结点head&#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 题目已知链表创建&#xff0c;并给了reverseList的函数头。 struct ListNode* reverseList(struct ListNode* he…

Maven属性与版本管理

文章目录 1 属性1.1 问题分析1.2 解决步骤步骤1:父工程中定义属性步骤2:修改依赖的version 2 配置文件加载属性步骤1:父工程定义属性步骤2:jdbc.properties文件中引用属性步骤3:设置maven过滤文件范围步骤4:测试是否生效 3 版本管理 在这一章节内容中&#xff0c;我们将学习两个…

ROS学习(1)——ROS1和ROS2的区别

因为机器人是一个系统工程&#xff0c;它包括了机械臂结构&#xff0c;电子电路&#xff0c;驱动程序&#xff0c;通信框架&#xff0c;组装集成&#xff0c;调试和各种感知决策算法等方面&#xff0c;任何一个人甚至是一个公司都不可能完成机器人系统的研发工作 。但是我们又希…

【黑科技】基于GPT开发的4款免费AI办公神器,实用又强悍!

今天给大家推荐4个非常实用且非常强悍的工具&#xff0c;基于GPT开发的AI工具 &#xff0c;每一款都能够大大提升我们的学习和工作效率 &#xff0c;希望你能看到并在收藏的同时点个赞或关注&#xff0c;万分感谢 。 Chat2doc 这是一个对学生党和打工人都特别有用的AI工具 &a…

西米支付:数字人民币常识普及

1.1 什么是数字人民币&#xff1f; 数字人民币 (英文简称&#xff1a; e-CNY) 是由人民银行发行的数字形式的法定货币 &#xff0c;由指定 运营机构参与运营 &#xff0c;以广义账户体系为基础 &#xff0c;支持银行账户松耦合功能 (意味着用户既可 以选择将数字人民币钱包与自…

GstOverlay 绑定多个gtk 窗口

主题说明 在spice stream 模式下&#xff0c;为了实现流畅的显示&#xff0c;利用gstvideooverlay 接口实现了gstreamer pipeline 的输出直接绑定到gtk 的窗口下。 然而spice客户端采用的是playbin 插件当前只能绑定一个窗口&#xff0c;当需要采用多窗口模式时&#xff0c;当…

VMware安装win10虚拟机教程及常见问题

win10虚拟机安装教程 一、前言 1. 准备VMware虚拟机&#xff08;可自行到VMware官网 或 点击链接 下载正版VMware Workstation Pro&#xff09;。 2. 准备需要安装的win10镜像&#xff0c;下载地址&#xff1a;下载 Windows 10。 3. 文章不一定合适每位安装虚拟机的人&#x…

代理模式及对startActivity的Hook应用

定义 简而言之&#xff0c;就是让代理类和目标类&#xff08;被代理类&#xff09;实现同一个接口&#xff0c;并让代理类持有一个目标类的对象&#xff0c;这样对代理类的访问&#xff0c;可以转移到目标类的访问中去。我们可以在不修改目标类的情况下&#xff0c;在代理类中实…