实验名称: 外部中断
信息与通信学院 电子信息工程
李保卫 0800220216 实验时间:第四周 星期一 第三大节
【实验目的】
1、学习LPC系列处理器向量中断控制器VIC的功能原理;
2、掌握外部中断引脚功能设置及外部中断的工作模式设置;
3、了解中断服务函数的编写方法。
【实验要求】
1、了解LPC系列处理器中断控制器的功能原理。
【实验原理】
一、LPC系列处理器中断控制器的原理
参见《ARM原理与嵌入式应用——基于LPC2400处理器和IAR开发环境》中有关中断系统的章节,重点要掌握向量中断控制器、外部中断引入以及系统控制寄存器中对外部中断的设置等。
二、实验板上的外部中断
1.原理图
2.说明
实验板上使用EINT0脚引入外部中断,在实验板上用一个按键实现。EINT0引脚先被上拉电阻上拉为高电平,当按键按下时,电平下降为低电平,因此中断方式应设置为下降沿触发。电路里的电容起到按键去抖动的功能。
三、驱动程序说明
1. irq.c说明
irq.c实现中断系统的初始化和中断服务子程序安装功能,它提供2个函数:
1) Init_VIC( ):对向量中断控制器VIC的初始化,一般由目标板启动初始化函数TargetResetInit( )调用;
2) install_irq ( ):将用户编写的中断服务函数安装,三个参数分别为中断号、中断服务函数地址、优先级。
2. extint.c说明
extint.c提供外部中断EINT0的驱动,它提供2个函数:
1) EINTInit( ):EINT0的初始化,实现EINT0使能、设置为下降沿触发、安装EINT0中断服务函数;
2) EINT0_Handler( ):EINT0中断服务函数,流程为:清除发生的EINT0中断、开中断、按键中断计数器eint0_counter加一、关中断、中断向量地址复位。其中按键中断计数器eint0_counter可以声明为外部全局变量,每发生一次按键中断自加一,用户即可在自己的应用程序中利用这个变量来实现不同的功能。
四、实验内容及程序代码
1、Init_VIC( )函数:
void init_VIC(void)
{ DWORD i = 0;
DWORD *vect_addr, *vect_cntl;
VICIntEnClr = 0xffffffff; // 使能全部清零
VICVectAddr = 0; // 默认向量地址为0
VICIntSelect=0; /*设置中断选择寄存器VICIntSelect,将32个中断请求全部分配为IRQ*/
for ( i = 0; i < VIC_SIZE; i++ ) // 32个中断服务向量复位
{
vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4);
vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4);
*vect_addr = 0x0; //中断服务函数都指向开头
*vect_cntl = 0xF; //优先级最低
}
return;
}
2、install_irq ( )函数:
DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
{
DWORD *vect_addr;
DWORD *vect_cntl;
VICIntEnClr=1< if ( IntNumber >= VIC_SIZE ) { return ( FALSE ); } else { /* find first un-assigned VIC address for the handler */ vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4); vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4); *vect_addr = (DWORD)HandlerAddr; /* set interrupt vector */ *vect_cntl = Priority; VICIntEnable=1< } } 3、EINTInit( )函数: DWORD EINTInit( void ) { PINSEL4=0x00100000; /*设置引脚功能选择寄存器PINSEL4,将P2.10作为外部中断0输入*/ IO2_INT_EN_F=0x200; /*设置GPIO下降沿中断使能寄存器IO2_INT_EN_F,Port2.10设置为下降沿触发,IO2_INT_EN_F(32位)与P2的32个IO一一对应,IO2_INT_EN_F某位为1时使能对应引脚下降沿中断*/ EXTMODE=EINT0_EDGE; /*设置外部中断方式寄存器EXTMODE,外部中断0使用边沿激活,*/ EXTPOLAR = 0; /* INT0 is falling edge by default */ if ( install_irq( EINT0_INT, (void *)EINT0_Handler, HIGHEST_PRIORITY ) == FALSE ) { return (FALSE); } return( TRUE ); } 4、EINT0_Handler ()函数: __irq __nested __arm void EINT0_Handler (void) { EXTINT = EINT0; /* clear interrupt */ __enable_interrupt(); /* handles nested interrupt */ eint0_counter++; /*中断计数器eint0_counter计数*/ __disable_interrupt(); /* handles nested interrupt */ VICVectAddr = 0; /* Acknowledge Interrupt */ } 5、main()函数: int main (void) { TargetResetInit(); /* initialize GPIO pins as external interrupts */ EINTInit(); GPIOInit(3,1,1); LedsInit(); /****** It's an endless loop waiting for external interrupt ******/ while( 1 ) { if ( (eint0_counter%2)==1) { LedOn(0);LedOn(1); LedOff(2);LedOff(3); } else { LedOn(2);LedOn(3); LedOff(0);LedOff(1); } } /*实验补充处1:利用if。。else。。语句,根据中断服务函数返回的计数值 eint0_counter的计数值为奇数次还是偶数次来点亮和熄灭不同的LED,如奇数次 时,点亮LED2和LED3,熄灭LED0和LED1;偶数次时,点亮LED0和LED1,熄灭LED2 和LED3。*/ return 0; } 【实验总结】 1、通过实验复习了嵌入式的编程方法; 2、学习LPC系列处理器向量中断控制器VIC的功能原理; 3、掌握外部中断引脚功能设置及外部中断的工作模式设置; 4、了解中断服务函数的编写方法。下载本文