學習KEA之週期中斷定時器PIT

我們以KEA64系列來學習週期中斷定時器PIT, 其中KEA64系列包括:

SKEAZN16AMLC®
SKEAZN32AMLC®
SKEAZN64AMLC®
SKEAZN32AMLH®
SKEAZN64AMLH®

PIT框圖

在這裏插入圖片描述

注: KEA64有1個PIT, 裏面又有2個獨立的通道PIT0和PIT1;我的理解就是兩個獨立的定時器。

PIT寄存器

在這裏插入圖片描述
這裏不展開來說明寄存器,具體地還是要看相應的手冊。

PIT時序

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

PIT用法之一:查詢標誌位

以PIT0爲例

基本步驟

  • 初始化時鐘(core clock和bus clock)
  • 初始化PIT
    • 使能 bus clock
    • 啓動 PIT
    • 加載PIT_LDVAL0或PIT_LDVAL1初始值
    • 啓動PIT定時器
  • 主循環
    • 查詢PIT定時器中斷標誌位
    • 清除中斷標誌位

定時1s例程

通過查詢方式,使LED每隔1s週期地閃爍

#include "derivative.h" /* include peripheral declarations SSKEAZN64M2 */

#define PTD2 26  /* Port PTD2, bit 26: output to blue LED */

void Clk_Init(void);
void init_PIT(void);

int main(void)
{
	Clk_Init();
	init_PIT();

	GPIOA_PDDR |= 1<<PTD2; /* Port D2: Data Direction= output */
	GPIOA_PIDR &= 1<<PTD2; /* Port D2: Input Disable= 1 (default) */

	for(;;)
	{
		while (0 == (PIT_TFLG0 & PIT_TFLG_TIF_MASK)) {}   /* Wait for PIT0 flag */
		PIT_TFLG0 |= PIT_TFLG_TIF_MASK;   /* Clear PIT0 flag */
		
		GPIOA_PTOR |= 1<<PTD2; /* Set Output on port D2 (LED on) */
	}
	
	return 0;
}


/***********************************************************************************************
*
* @brief    CLK_Init - Initialize Core Clock to 40MHz, Bus Clock to 20MHz
* @param    none
* @return   none
*
************************************************************************************************/
void Clk_Init(void)
{
	OSC_CR = 0x00;      /* (default value) */
						/* OSCEN=0: OSC module disabled */
						/* OSCSTEN=0: OSC clock disabled in Stop mode */
						/* OSCOS=0: Ext clk source (don't care here) */
						/* RANGE=0: Low Freq range of 32 KHz */
						/* HGO=0: low power High Gan Osc mode (don't care here) */

	 ICS_C1|=ICS_C1_IRCLKEN_MASK; /* Enable the internal reference clock*/
	 ICS_C3= 0x50; /* Reference clock frequency =  39.0625 kHz*/

	 while(!(ICS_S & ICS_S_LOCK_MASK)); /* Wait for PLL lock, now running at 40 MHz (1024*39.0625 kHz) */

	 ICS_C2|=ICS_C2_BDIV(1) ; /*BDIV=2, Bus clock = 20 MHz*/
	 ICS_S |= ICS_S_LOCK_MASK ; /* Clear Loss of lock sticky bit */
}

/***********************************************************************************************
*
* @brief    init_PIT - 設定定時器週期溢出時間1s, 沒有啓動中斷,需要外部查詢溢出標誌位
* @param    none
* @return   none
*
************************************************************************************************/
void init_PIT(void)
{
	SIM_SCGC |= SIM_SCGC_PIT_MASK;     /* Enable bus clock to PIT module */
	PIT_MCR = 0x0;                     /* Turn on PIT module, Freeze disabled */
	PIT_LDVAL0 = 20000000 - 1;         /* PIT0: Load value to count 20M bus clocks */
	PIT_TCTRL0 |= PIT_TCTRL_TEN_MASK;  /* PIT0: Start timer */

	PIT_TCTRL0 |= PIT_TCTRL_TEN_MASK;
}

PIT用法之二:中斷

以PIT1爲例

基本步驟

  • 初始化時鐘(core clock和bus clock)
  • 初始化中斷
    • Clear any prior pending PIT channel 1 interrupt
    • Enable PIT channel 1 interrupt
    • Set PIT channel 1 interrupt priority from 0 to 3 (3 is highest)
  • 初始化PIT
    • 使能 bus clock
    • 啓動 PIT
    • 加載PIT_LDVAL0或PIT_LDVAL1初始值
    • 允許PIT中斷
    • 啓動PIT定時器
  • PIT1中斷服務程序
    • 清除中斷標誌位

定時1s例程

以PIT1爲例 ,通過中斷方式,使LED每隔1s週期地閃爍

#include "derivative.h" /* include peripheral declarations SSKEAZN64M2 */

#define PTD2 26  /* Port PTD2, bit 26: output to blue LED */

void Clk_Init(void);
void init_IRQs(void);
void init_PIT(void);

int main(void)
{
	Clk_Init();
	init_IRQs();
	init_PIT();

	GPIOA_PDDR |= 1<<PTD2; /* Port D2: Data Direction= output */
	GPIOA_PIDR &= 1<<PTD2; /* Port D2: Input Disable= 1 (default) */

	for(;;)
	{
		;
	}

	return 0;
}

/***********************************************************************************************
*
* @brief    CLK_Init - Initialize Core Clock to 40MHz, Bus Clock to 20MHz
* @param    none
* @return   none
*
************************************************************************************************/
void Clk_Init(void)
{
	OSC_CR = 0x00;      /* (default value) */
						/* OSCEN=0: OSC module disabled */
						/* OSCSTEN=0: OSC clock disabled in Stop mode */
						/* OSCOS=0: Ext clk source (don't care here) */
						/* RANGE=0: Low Freq range of 32 KHz */
						/* HGO=0: low power High Gan Osc mode (don't care here) */

	 ICS_C1|=ICS_C1_IRCLKEN_MASK; /* Enable the internal reference clock*/
	 ICS_C3= 0x50; /* Reference clock frequency =  39.0625 kHz*/

	 while(!(ICS_S & ICS_S_LOCK_MASK)); /* Wait for PLL lock, now running at 40 MHz (1024*39.0625 kHz) */

	 ICS_C2|=ICS_C2_BDIV(1) ; /*BDIV=2, Bus clock = 20 MHz*/
	 ICS_S |= ICS_S_LOCK_MASK ; /* Clear Loss of lock sticky bit */
}


/***********************************************************************************************
*
* @brief    init_PIT - 設定定時器週期溢出時間1s, 啓動中斷
* @param    none
* @return   none
*
************************************************************************************************/
void init_PIT(void)
{
	SIM_SCGC |= SIM_SCGC_PIT_MASK;     /* Enable bus clock to PIT module */
	PIT_MCR = 0x0;                     /* Turn on PIT module, Freeze disabled */
	PIT_LDVAL1 = 20000000 - 1;         /* PIT1: Load value to count 20M bus clocks */
	PIT_TCTRL1 |= PIT_TCTRL_TIE_MASK;  /* Enable interrupt */
	PIT_TCTRL1 |= PIT_TCTRL_TEN_MASK;  /* PIT1: Start timer */

	PIT_TCTRL1 |= PIT_TCTRL_TEN_MASK;
}

/***********************************************************************************************
*
* @brief    init_IRQs
* @param    none
* @return   none
*
************************************************************************************************/
void init_IRQs(void)
{
	NVIC_ClearPendingIRQ(PIT_CH1_IRQn);  /* Clear any Pending IRQ for all PIT ch1 (#23) */
	NVIC_EnableIRQ(PIT_CH1_IRQn);        /* Set Enable IRQ for PIT_CH1 */
	NVIC_SetPriority(PIT_CH1_IRQn,0);    /* Set Priority for PIT_CH1 */
}

/***********************************************************************************************
*
* @brief    PIT_CH1_IRQHandler - PIT CH1中斷程序
* @param    none
* @return   none
*
************************************************************************************************/
void PIT_CH1_IRQHandler (void)
{
	PIT_TFLG1 |= PIT_TFLG_TIF_MASK; /* Clear PIT1 flag */

	GPIOA_PTOR |= 1<<PTD2; /* Set Output on port D2 (LED on) */
}

上面兩個例程的結果如下:
在這裏插入圖片描述

小結

  • PIT有兩個獨立的通道: PIT0和PIT1
  • PIT時鐘來自bus clock
  • 當PIT_LDVAL0或PIT_LDVAL1 初始值減到0的時候,便會產生一個定時中斷標誌,同時也會自動加載這個初始值,以便產生下一個週期的定時中斷標誌
  • 產生中斷標誌後,一定要手動清除這個標誌位,不然不會進入下一個中斷週期
  • PIT有兩種用法:中斷標誌位查詢法 和 中斷服務程序法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章