1、开发环境
LPC-2478STK+IAR+JINK
2、特性
- 32 位的定时器/计数器,带有一个可编程的 32 位预分频器。
- 计数器或定时器操作。
- 每个定时器包含多达 4 个 32 位的捕获通道,可以在输入信号变化时捕捉定时器的瞬时值。捕获事件也可以选择产生中断。
- 4 个 32 位匹配寄存器,允许执行以下操作:
- 连续工作,在匹配时可选择产生中断
- 在匹配时停止定时器运行,可选择产生中断
- 在匹配时复位定时器,可选择产生中断
- 有多达 4 个外部输出与匹配寄存器相对应,这些输出具有以下功能:
- - 匹配时设为低电平。
- - 匹配时设为高电平。
- - 匹配时翻转。
- - 匹配时不执行任何操作。
3、相关寄存器
3.1、中断寄存器T[0/1/2/3]IR
中断寄存器包含 4 个位用于匹配中断, 4 个位用于捕获中断。如果有中断产生, IR 中的对应位会置位,否则为 0。向对应的 IR 位写入 1 会复位中断。写入 0 无效。
3.2、定时器控制寄存器T[0/1/2/3]CR
定时器控制寄存器(TCR)用来控制定时器/计数器的操作。
3.3、计数控制寄存器T[0/1/2/3]CTCR
计数控制寄存器(CTCR)用来在定时器模式和计数器模式之间进行选择,在计数器模式中选择计数的管脚和边沿
3.4、匹配寄存器MR0 – MR3
匹配寄存器值连续与定时器计数值相比较。当两个值相等时自动触发相应动作。这些动作包括产生中断,复位定时器计数器或停止定时器。所执行的动作由 MCR 寄存器控制。
3.5、匹配控制寄存器T[0/1/2/3]MCR
匹配控制寄存器用来控制在发生匹配时所执行的操作
3.6、捕获寄存器CR0-CR3
每个捕获寄存器都与一个器件管脚相关联。当管脚发生特定的事件时,可将定时器计数器的值装入该寄存器。捕获控制寄存器的设定决定捕获功能是否被使能以及捕获事件在管脚的上升沿、下降沿还是双边沿发生。
3.7、捕获控制寄存器T[0/1/2/3]CCR
捕获控制寄存器用来控制在捕获事件发生时是否将定时器计数器的值装入其中一个捕获寄存器以及是否产生中断。同时设置上升沿和下降沿位也是有效的配置,这样会在两个边沿都触发捕获事件。在下面的描述中,“n”代表定时器的编号 0 或 1。
3.8、外部匹配寄存器T[0/1/2/3]EMR
外部匹配寄存器提供外部匹配管脚的控制和状态。在下面的描述中,“n”代表定时器编号,值为 0 或 1;“m”代表匹配编号,值为 0~3
3.9、其他寄存器
- PR->预分频寄存器
- TC->定时器计数器
- PC->预分频计数器
4、代码实现
代码功能:实现LED周期性闪烁
#include <nxp/iolpc2478.h>
#include <intrinsics.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u64;
typedef unsigned long u32;
#ifndef NULL
#define NULL ((void*)0)
#endif
/* P1[13] 低电平导通 */
#define led1 13
/* P1[18] 低电平导通 */
#define led2 18
/* P2[19] 按下低电平,悬空高电平 */
#define but1 19
/* P2[21] 按下低电平,悬空高电平 */
#define but2 21
#define led1_on (FIO1CLR |= 0x01 << led1)
#define led1_off (FIO1SET |= 0x01 << led1)
#define led2_on (FIO1CLR |= 0x01 << led2)
#define led2_off (FIO1SET |= 0x01 << led2)
void enable_fast_port()
{
SCS |= 1 << 0;
}
void gpio_init()
{
PINSEL2 &= ~(0x03 << led1*2);
FIO1DIR &= ~(0x01 << led1);
FIO1DIR |= 0x01 << led1;
led1_off;
PINSEL3 &= ~(0x03 << ((led2 % 16)*2));
FIO1DIR &= ~(0x01 << led2);
FIO1DIR |= 0x01 << led2;
led2_off;
PINSEL5 &= ~(0x03 << ((but1 % 16)*2));
PINSEL5 |= (0x0 << ((but1 % 16)*2));
FIO2DIR &= ~(0x01 << but1);
PINSEL5 &= ~(0x03 << ((but2 % 16)*2));
PINSEL5 |= (0x0 << ((but2 % 16)*2));
FIO2DIR &= ~(0x01 << but2);
}
void led1_reverse(void)
{
if ((FIO1SET & (0x01 << led1)) == 0)
led1_off;
else
led1_on;
}
void led2_reverse(void)
{
if ((FIO1SET & (0x01 << led2)) == 0)
led2_off;
else
led2_on;
}
__irq __arm void IRQ_Handler (void)
{
void (*interrupt_function)();
unsigned int vector;
vector = VICADDRESS; // Get interrupt vector.
interrupt_function = (void(*)())vector;
if(interrupt_function != NULL)
{
interrupt_function(); // Call vectored interrupt function.
}
else
{
VICADDRESS = 0; // Clear interrupt in VIC.
}
}
void VIC_SetVectoredIRQ(void(*pIRQSub)(), unsigned int Priority,
unsigned int VicIntSource)
{
unsigned long volatile *pReg;
// load base address of vectored address registers
pReg = &VICVECTADDR0;
// Set Address of callback function to corresponding Slot
*(pReg+VicIntSource) = (unsigned long)pIRQSub;
// load base address of ctrl registers
pReg = &VICVECTPRIORITY0;
// Set source channel and enable the slot
*(pReg+VicIntSource) = Priority;
// Clear FIQ select bit
VICINTSELECT &= ~(1<<VicIntSource);
}
/* 正常寄存器写法 */
void timer0_irq(void)
{
led1_reverse();
T0IR |= 1;
VICADDRESS = 0;
}
void timer0_init(void)
{
PCONP |= 1 << 1;
T0MR0 = 1000000;/* 1s一次 */
T0MCR = 3;
T0IR = 1;
VIC_SetVectoredIRQ(timer0_irq,1,VIC_TIMER0);
VICINTENABLE |= 1 << VIC_TIMER0;
T0TCR = 1;
__enable_interrupt();
}
/* lpc2470版的位域写法 */
void timer1_irq(void)
{
led2_reverse();
T1IR_bit.MR0INT = 1;
VICADDRESS = 0;
}
void timer1_init(void)
{
PCONP_bit.PCTIM1 = 1;
// Init Time0
T1TCR_bit.CE = 0; // counting disable
T1TCR_bit.CR = 1; // set reset
T1TCR_bit.CR = 0; // release reset
T1CTCR_bit.CTM = 0; // Timer Mode: every rising PCLK edge
T1MCR_bit.MR0I = 1; // Enable Interrupt on MR0
T1MCR_bit.MR0R = 1; // Enable reset on MR0
T1MCR_bit.MR0S = 0; // Disable stop on MR0
// set timer 0 period
T1PR = 0;
T1MR0 = 1000000;
// init timer 0 interrupt
T1IR_bit.MR0INT = 1; // clear pending interrupt
VIC_SetVectoredIRQ(timer1_irq,1,VIC_TIMER1);
VICINTENABLE |= 1UL << VIC_TIMER1;
T1TCR_bit.CE = 1; // counting Enable
__enable_interrupt();
}
/* 当多个引脚使用同一个定时器的MAT输出时,频率需要一致,否则不一致的将无效 */
void timer2_mat_init(void)
{
PINSEL0 &= ~(0x03 << (9*2)); /* p0[9] MAT2[3]*/
PINSEL0 |= (0x03 << (9*2));
PCONP |= 1 << 22;
T2PR = 0; /* 分频 */
T2MCR = 0x03 << 9; /* 并且匹配时产生中断 */
T2EMR = 0x03 << 10; /* T2MR3匹配后MAT2.3输出翻转 */
T2MR3 = 1000000; /* 转输出(注意已经分了频) */
T2TCR = 0x03;
VICIntSelect = 0x00; /* 所有的中断连接IRQ中断 */
VIC_SetVectoredIRQ(timer1_irq,1,VIC_TIMER2);
VICINTENABLE |= 1UL << VIC_TIMER2; /* 使能定时器 */
T2TCR = 0x01;
}
int main(void)
{
enable_fast_port();
gpio_init();
timer0_init();
timer1_init();
while(1)
{
}
}