定时器有三个内容,定时、PWM还有捕获。本节是最后一个:捕获。
捕获功能是指,定时器可以在某个引脚发生某种电平变化的时候,做出相应的反应。在《LPC130 user mannal》里面对定时器捕获功能进行描述的寄存器只有2个,是很简单的。我们从这两个寄存器剖析32位定时器的捕获功能。
第一个:捕获控制寄存器
18.jpg (58.04 KB)
2010-6-7 12:41
从这个寄存器我们可以看到,定时器在捕获某个引脚有电平变化时,产生对应反应:
1、当对应引脚产生上升沿时,将TC的内容装入CR0;
2、当对应引脚产生下降沿时,将TC的内容装入CR0;
3、CR0装载事件的触发,导致一个中断的产生;
CR0是什么呢?是捕获寄存器:
★
各捕获寄存器(TMR32B0CR0-地址0x4001 402C和TMR32B1CR0-地址0x4001 802C)与器件管脚相关联,当管脚发生特定的事件时,可将定时器计数器的值装入该捕获寄存器。捕获控制寄存器中的设置决定是否使能捕获功能,以及在相关管脚的上升沿、下降沿或双边沿时是否产生捕获事件。
以上两个寄存器就是用来设置定时器捕获功能的所有寄存器,是很简单的。
直白的说,捕获功能就是在某个引脚产生跳变事件之时,将当前定时器值记录,并根据用户的设置选择是否产生中断。
由此就很轻易能想到,利用这个捕获功能我们可以计算出两次捕获事件的时间差,还有记录跳变沿的数目。这次我们尝试设计一个实验,记录LED闪烁的次数。程序由PWM示例更改而来,
首先是主函数:
init_timer32(0, TIME_INTERVAL);//初始化32定时器0,设置定时间隔
enable_timer32(0);//使能32位定时器0
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);//开启AHB时钟
GPIOSetDir( LED_PORT, LED_BIT, 1 );//设置唯一个LED的IO
/*此大循环里面为模拟50%的PWM信号驱动LED闪烁*/
if ( (timer32_0_counter > 0) && (timer32_0_counter <= 50) )
GPIOSetValue( LED_PORT, LED_BIT, LED_OFF );
if ( (timer32_0_counter > 50) && (timer32_0_counter <= 100) )
GPIOSetValue( LED_PORT, LED_BIT, LED_ON );
else if ( timer32_0_counter > 100 )
}
我们在前一节已经讲述了关于定时器时间间隔的设置过程,在此不在阐述,由此大循环里面的模拟PWM也非常容易看懂的了。timer32_0_counter在0-100之间计数,逢50跳转高电平,逢100跳转低电平,由此得到周期为100,高电平周期为50的50%占空比的PWM信号。
大家肯定很容易猜得到,在这个主函数里面对定时器捕获功能进行设置的肯定在
init_timer32(0, TIME_INTERVAL);
void init_timer32(uint8_t timer_num, uint32_t TimerInterval)
{
if ( timer_num == 0 )
{
/* Some of the I/O pins need to be carefully planned if
you use below module because JTAG and TIMER CAP/MAT pins are muxed. */ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9);
LPC_IOCON->PIO1_5 &= ~0x07;
/*
Timer0_32 I/O config */
LPC_IOCON->PIO1_5 |= 0x02;
/* Timer0_32 CAP0 */
LPC_IOCON->PIO1_6 &= ~0x07;
LPC_IOCON->PIO1_6 |= 0x02;
/* Timer0_32 MAT0 */
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x02;
/* Timer0_32 MAT1 */
LPC_IOCON->PIO0_1 &= ~0x07;
LPC_IOCON->PIO0_1 |= 0x02;
/* Timer0_32 MAT2 */
#ifdef __JTAG_DISABLED
LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x07;
LPC_IOCON->JTAG_TDI_PIO0_11 |= 0x03;
/* Timer0_32 MAT3 */
#endif
#ifdef TIMER32_0_DEFAULT_HANDLER
timer32_0_counter = 0;
timer32_0_capture = 0;
#endif //TIMER32_0_DEFAULT_HANDLER
LPC_TMR32B0->MR0 = TimerInterval;
#if TIMER_MATCH
LPC_TMR32B0->EMR &= ~(0xFF<<4);
LPC_TMR32B0->EMR |= ((0x3<<4)|(0x3<<6)|(0x3<<8)|(0x3<<10));
/* MR0/1/2/3 Toggle */
#else
/* ★Capture 0 on rising edge, interrupt enable. ★*/
LPC_TMR32B0->CCR = (0x1<<0)|(0x1<<2)|(0x1<<1);
#endif
LPC_TMR32B0->MCR = 3;
/* Interrupt and Reset on MR0 */
/* Enable the TIMER0 Interrupt */
NVIC_EnableIRQ(TIMER_32_0_IRQn);
}
else if ( timer_num == 1 )
{
/*此部分内容和上半部分类同*/
}
return;
}
这里我们特地做了明显的标记,蓝色部分是一个#if…#else…#endif预编译语句,而蓝色部分包含的红色语句就是这个初始化函数里面对定时器捕获功能的唯一一句设置语句。什么时候会将这个设置语句编译呢?各位肯定知道取决于TIMER_MATCH这个宏定义过的变量。很容易查看到(在timer32.h):
#define TIMER_MATCH
0
可以看到默认情况下,该定时器初始化函数选择捕获功能,另一种情况是外部匹配功能。
LPC_TMR32B0->CCR = (0x1<<0)|(0x1<<2)|(0x1<<1); |