高精度延時
阿新 • • 發佈:2021-11-25
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); } }