一、概述
LPC54608 的 MRT (Multi-Rate Timer) 是一个 24bit 中断定时器,它提供了四个独立计数通道,具有重复中断、单次中断和单次暂停三种模式。
二、MRT 简介
2.1 结构框图
MRT 的结构框图如下所示,它提供 4 个通道的重复性中断定时器,每通道经过编程后可具有独立的时间间隔。
图 1. MRT 结构框图
2.2 工作模式
2.2.1 重复中断模式
重复中断模式会在指定的时间间隔后产生重复中断,这种模式可以用于基于软件的 PWM 或 PPM 应用程序。
当定时器 n 处于空闲状态时,向 INTVALn 寄存器写入一个非零值IVALUE,会立即加载时间间隔值 IVALUE – 1 ,计时器从这个值开始倒数,当定时器达到 0 时,产生一个中断, VALUE – 1 被自动重新加载到 INTVALn 寄存器,计时器再次开始倒计时。
2.2.2 单次中断模式
单次中断在一次计数后生成一个中断。在这种模式下,可以在任何点生成单个中断。该模式可用于在软件任务中引入特定的延迟。
当定时器处于空闲状态时,向 INTVALn 寄存器写入一个非零值 IVALUE,立即加载时间间隔值 IVALUE - 1,定时器开始倒计时,当定时器达到 0 时,产生中断,定时器停止,进入空闲状态。
2.2.3 单次暂停模式
单次暂停模式与单次中断模式相似,不同之处在于它用于非常短的延迟,例如,当所需的延迟小于到达中断服务程序所需的时间时。这种模式是为非常低的软件开销而设计的,只需要对 INTVALn 寄存器进行一次写入(如果通道已经配置为单次暂停模式)。
MRT 在暂停总线写操作时请求延迟,当延迟完成时结束写操作,不需要中断或状态轮询。当两个软件控制事件之间需要一个短延迟时,或者当软件可以继续之前希望有一个延迟时,可以使用总线暂停模式。由于在此模式中,在 MRT 向下计数时没有总线事务,因此 CPU 在这段时间内消耗的能量最小。
注意,总线暂停模式在执行写入 INTVAL 的指令和软件继续运行之间提供了最短的时间。其他系统事件,例如中断或访问 MRT 所在的 APB 总线的其他总线主机,可能会导致延迟更长。
三、MRT 使用
3.1 初始化 MRT
初始化多速率定时器,主要包含使能时钟等操作,如下图。
图 2. 初始化 MRT
3.2 设置通道和模式
总共有 4 个通道( 0 - 3 ),这里我们使用通道 0 ,工作模式选择重复中断模式,如下图所示。
图 3. 配置 MRT 通道和模式
3.3 使能中断
使能使用通道对应的中断,如下图。
图 4. 使能中断
3.4 设置计数值并开始计时
设置计数值,注意,24bit 计数上限为 0x00FF FFFF ,所赋的计数值应不超过其上限,如下图。
图 5. 设置计数值
四、LPC54608 之 MRT 应用实验
4.1 实验目的
通过本实验,理解并掌握 MRT 的应用。
4.2 开发环境
硬件: LPC54608 开发板
软件: MCUXpresso 开发环境,SDK_2.9.0_LPC54608J512
4.3 实验描述
本实验以每隔 50ms 翻转 LED 为例,使用 MRT 进行计时和中断。
4.4 软件设计
/*********************** Standard C Included Files ***********************/
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "board.h"
#include "fsl_mrt.h"
#include "stdbool.h"
/****************************** Definitions ******************************/
#define APP_LED_INIT (LED3_INIT(1));
#define APP_LED_ON (LED3_ON());
#define APP_LED_TOGGLE (LED3_TOGGLE());
#define MRT_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)
/******************************* Variables *******************************/
static volatile bool mrtIsrFlag = false;
/********************************* Code *********************************/
void MRT0_IRQHandler(void)
{
/* Clear interrupt flag.*/
MRT_ClearStatusFlags(MRT0, kMRT_Channel_0, kMRT_TimerInterruptFlag);
mrtIsrFlag = true;
SDK_ISR_EXIT_BARRIER;
}
int main(void)
{
uint32_t mrt_clock;
/* Structure of initialize MRT */
mrt_config_t mrtConfig;
/* Board pin, clock, debug console init */
/* enable clock for GPIO; used to toggle the LED's */
CLOCK_EnableClock(kCLOCK_Gpio2);
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitPins();
BOARD_BootClockPLL220M();
BOARD_InitDebugConsole();
/* Initialize and enable LED */
APP_LED_INIT;
mrt_clock = MRT_CLK_FREQ;
/* mrtConfig.enableMultiTask = false; */
MRT_GetDefaultConfig(&mrtConfig);
/* Init mrt module */
MRT_Init(MRT0, &mrtConfig);
/* Setup Channel 0 to be repeated */
MRT_SetupChannelMode(MRT0, kMRT_Channel_0, kMRT_RepeatMode);
/* Enable timer interrupts for channel 0 */
MRT_EnableInterrupts(MRT0, kMRT_Channel_0, kMRT_TimerInterruptEnable);
/* Enable at the NVIC */
EnableIRQ(MRT0_IRQn);
uint32_t count = (50) * (mrt_clock) / 1000U;
if(count <= 0xFFFFFF)
{
MRT_StartTimer(MRT0, kMRT_Channel_0, count);
}
while (true)
{
/* Check whether occur interupt and toggle LED */
if (true == mrtIsrFlag)
{
PRINTF("\r\n Channel No.0 interrupt is occurred !");
APP_LED_TOGGLE;
mrtIsrFlag = false;
}
}
}
4.5 实验结果
在串口助手上可以看到 MRT 中断提示,同时,抓取 LED 引脚波形,如下图。
图 6. LED 引脚波形
五、参考资料
(1)LPC546XX 系列相关资料均可在 NXP 官网下载,网址如下: