学习KEA之周期中断定时器PIT
程序员文章站
2024-02-25 14:55:45
...
我们以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有两种用法:中断标志位查询法 和 中断服务程序法
下一篇: Linux系统上搭建Redis分布式集群