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.mfbz.cn/a/135283.html

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

相关文章

CCF ChinaSoft 2023 论坛巡礼 | CCF-华为胡杨林基金-形式化方法专项(海报)论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

Java实现音频转码,WAV、MP3、AMR互转

1.背景 最近在集成一款产品支持语音双向对讲&#xff0c;首先是采集小程序的音频下发给设备端&#xff0c;然后可以控制设备录音生成音频链路让小程序播放。在这个过程中发现&#xff0c;设备除了AMR格式的音频外&#xff0c;其他的音频都不支持&#xff0c;而微信小程序有不支…

LangChain应用全解析

一、Langchain基础 1.Langchain简介 (1)替换模型 from langchain.prompts import ChatPromptTemplatechat ChatOpenAI(temperature0) 使用代理ip llm ChatOpenAI(model_name"gpt-3.5-turbo", max_tokens2048, temperature0.5,openai_api_keyapi_key,openai_ap…

docker stop slow 解决

验证 NanoMQ stop slow 的问题 daemon 和非 daemon 两种方式 docker stop 都很慢 疑问是默认情况下&#xff0c;SIGTERM 会被处理。 模拟 docker 内发送 SIGTERM 信号 # The default signal for kill is TERM # pkill will send the specified signal (by defau…

海康Visionmaster-环境配置:CSharp 二次开发环境配 置方法

C#二次开发环境的配置方法 以 WinForm 为例&#xff0c;进行 VM 二次开发的环境配置分为三步&#xff1a; 第一步&#xff0c;使用 VS 新建一个框架为.NET Framework 4.6.1 的工程&#xff0c;平台首选 32 位取消勾选&#xff0c;重新生成解决方案&#xff0c;保证工程 Debug 下…

c++ 信奥编程 1135:配对碱基链

#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main(){char a[256];int len;int i;gets(a);lenstrlen(a);//计算字符串长度for(i0; i<len; i){ //输出配对碱基if(a[i]A) cout<<"T";if(a[i]T) cout<…

【java:牛客每日三十题总结-6】

java:牛客每日三十题总结 总结如下 总结如下 transient 变量和序列化有关&#xff0c;这是一个空接口&#xff0c;起标记作用&#xff0c;具体的序列化由ObjectOutputStream和ObjectInputStream完成。transient修饰的变量不能被序列化&#xff0c;static变量不管加没加transie…

C51--PC通过串口(中断)点亮LED

B4中的&#xff1a;REN允许 / 禁止串行接收控制位 REN 1为允许串行接收状态。 接收数据必须开启。所以SCON&#xff1a;0101 0000 &#xff1b;即0x50 如何知道数据已经接收 RI位&#xff1a;当收到数据后 RI 1&#xff08;由硬件置一&#xff09; 硬件置一后必须用软件…

开放领域问答机器人2——开发流程和方案

开放领域问答机器人是指在任何领域都能够回答用户提问的智能机器人。与特定领域问答机器人不同&#xff0c;开放领域问答机器人需要具备更广泛的知识和更灵活的语义理解能力&#xff0c;以便能够回答各种不同类型的问题。 开发开放领域问答机器人的流程和方案可以包括以下步骤…

Pytroch损失函数、反向传播和优化器、Sequential使用

Pytroch_Sequential使用、损失函数、反向传播和优化器 文章目录 nn.Sequential搭建小实战损失函数与反向传播优化器 nn.Sequential nn.Sequential是一个有序的容器&#xff0c;用于搭建神经网络的模块被按照被传入构造器的顺序添加到nn.Sequential()容器中。 import torch.nn …

[html] 动态炫彩渐变背景

废话不多说&#xff0c;直接上源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>ZXW-NUDT: 动态炫…

交叉编译 openssl

要在 x86 平台上编译适用于 aarch64 架构的 OpenSSL 动态库&#xff0c;你需要使用交叉编译工具链。可以按照以下步骤进行&#xff1a; 安装 aarch64 交叉编译工具链&#xff1a; $ sudo apt-get install gcc-aarch64-linux-gnu g-aarch64-linux-gnu 这将安装 aarch64 交叉编…

大力说运营:如何战胜每日的头疼难题?

小美是一名微信公众号运营专员&#xff0c;近几个月来&#xff0c;每当想到去上班&#xff0c;她就感到全身无力&#xff0c;焦虑烦躁。 原来老板要求小美每天都发一篇推文&#xff0c;而且选题要有吸引力&#xff0c;经过这几个月的苦肝&#xff0c;小美感觉身体被掏空&#x…

【免费送书】蒙古包头旅游和美食推荐

【点我-这里送书】 本人详解 作者&#xff1a;王文峰&#xff0c;参加过 CSDN 2020年度博客之星&#xff0c;《Java王大师王天师》 公众号&#xff1a;JAVA开发王大师&#xff0c;专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生&#xff0c;期待你的…

JLink edu mini 10Pin接口定义

注意&#xff1a;SWD接口在阵脚2&#xff0c;4&#xff1b;而20Pin的SWD接口在阵脚7&#xff0c;9 参考&#xff1a;1 官网资料&#xff1b; 2 【润石RS0104YQ Demo开发板测试分享】J-Link EDU Mini调试5V系统_国产运算放大器_模拟开关_线性稳压器_电平转换器_小逻辑_比较器…

头歌答案HTML——基础

目录 HTML——基础 第1关&#xff1a;初识HTML&#xff1a;简单的Hello World网页制作 任务描述 第2关&#xff1a;HTML结构&#xff1a;自我简介网页 任务描述 HTML——基本标签 第1关&#xff1a;创建第一个 HTML 标签 任务描述 第2关&#xff1a;创建 任务描述 …

社会公益服务小程序的作用是什么

公益包含的项目比较广&#xff0c;包括助学、环保、关爱特殊群体等&#xff0c;市场中无论相关机构还是团队&#xff0c;都有不少&#xff0c;而在实际运作中&#xff0c;也有些一些难题&#xff1a; 首先就是信息展示方面&#xff0c;自身服务及案例难以展示&#xff0c;线上…

「题解」反转链表 返回中间节点

文章目录 &#x1f349;题目1&#xff1a;反转链表&#x1f349;解析&#x1f34c;解法一&#xff1a;创建一个新链表&#x1f34c;解法二&#xff1a;直接操作原链表 &#x1f349;题目2&#xff1a;返回中间节点&#x1f34c;解法一&#xff1a;快慢指针&#x1f34c;解法二&…

通过 Elasticsearch 和 Go 使用混合搜索进行地鼠狩猎

作者&#xff1a;CARLY RICHMOND&#xff0c;LAURENT SAINT-FLIX 就像动物和编程语言一样&#xff0c;搜索也经历了不同实践的演变&#xff0c;很难在其中做出选择。 在本系列的最后一篇博客中&#xff0c;Carly Richmond 和 Laurent Saint-Flix 将关键字搜索和向量搜索结合起…

中国建设银行转账模拟器,工商农业邮政中国招商假的回执单,易语言轻松实现

用易语言的选择夹画板黑月透明标签编辑框实现了一个假的转账模拟器&#xff0c;当然我还是加了水印的&#xff0c;这个图片你也用不了&#xff0c;只能是学习研究一下源码的实现逻辑&#xff0c;知道画板是怎么对编辑框输入的内容做出反应的&#xff0c;然后是如何获取画板上面…
最新文章