高精度延时
1. 步骤
GPTx_CR寄存器
GPTx_SR寄存器
GPTx_PR寄存器分频
1、设置 GPT1 定时器
首先设置 GPT1_CR 寄存器的 SWR(bit15)位来复位寄存器 GPT1。复位完成以后设置寄存
器 GPT1_CR 寄存器的 CLKSRC(bit8:6)位,选择 GPT1 的时钟源为 ipg_clk。设置定时器 GPT1
的工作模式,
2、设置 GPT1 的分频值
设置寄存器 GPT1_PR 寄存器的 PRESCALAR(bit111:0)位,设置分频值。
3、设置 GPT1 的比较值
如果要使用 GPT1 的输出比较中断,那么 GPT1 的输出比较寄存器 GPT1_OCR1 的值可以
根据所需的中断时间来设置。本章例程不使用比较输出中断,所以将 GPT1_OCR1 设置为最大
值,即:0XFFFFFFFF。 4、使能 GPT1 定时器
设置好 GPT1 定时器以后就可以使能了,设置 GPT1_CR 的 EN(bit0)位为 1 来使能 GPT1 定
时器。
5、编写延时函数
GPT1定时器已经开始运行了,可以根据前面介绍的高精度延时函数原理来编写延时函数,
针对 us 和 ms 延时分别编写两个延时函数。
2.代码
bsp_delay.h
#ifndef __BSP_DELAY_H
#define __BSP_DELAY_H
#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);
#endif
bsp_delay.c
#include "bsp_delay.h"
/*
* @description : 延时有关硬件初始化,主要是 GPT 定时器
GPT 定时器时钟源选择 ipg_clk=66Mhz
* @param : 无 7 * @return : 无 8 */
void delay_init(void)
{
GPT1->CR = 0; /* 清零 */
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
*/
GPT1->CR = (1<<6);
/*
* GPT 的 PR 寄存器,GPT 的分频设置
* bit11:0 设置分频值,设置为 0 表示 1 分频,
* 以此类推,最大可以设置为 0XFFF,也就是最大 4096 分频
*/
GPT1->PR = 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; /* 66 分频,GPT1 时钟为 66M/(65+1)=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 – usdelay : 需要延时的 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--){}
}
void delay(volatile unsigned int n)
{
while(n--)
{
delay_short(0x7ff);
}
}
主要是给自己看的,所以肯定会出现很多错误哈哈哈哈哈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律