1. 程式人生 > 其它 >高精度延時

高精度延時

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

主要是給自己看的,所以肯定會出現很多錯誤哈哈哈哈哈