ARM中断程序之外部中断
----------------------------------------------------------------------
Author :tiger-john
WebSite :blog.csdn.net/tigerjb
Email :[email protected]
开发板 :LPC220
环境 :ADS1.2
Tiger声明:本人鄙视直接复制本人文章而不加出处的个人或团体,但不排斥别人转载tiger-john的文章,只是请您注明出处并和本人联系或留言给我。3Q
-----------------------------------------------------------------------
目录:
ARM2200下的中断编程一
ARM2200下的中断编程二
ARM2200 下的中断编程三
四.ARM中断程序编写之外部中断
前言:VIC中断控制器定义了4个外部中断,中断号为EINT0(14),
EINT1(15),EINT2(16),EINT3(17)用来给用户进行编写外部中断(例如按键中断。。。)
1. 在编写外部中断事先要对引脚功能选择寄存器(PINSEL0)进行配置
(参照具体型号的ARM数据手册,此处以LPC2230进行配置)在LPC2230中:
Eg:PINSEL1 = 3<<8; // 设置管脚连接,P0.20设置为EINT3
2第二部外部中断还要对外部中断方式寄存器(EXTMODE)进行配置来选择每个EINT脚是电平触发还是边沿触发。
A.EXTMODE(外部中断方式寄存器):总共有8位
第0位:对第0位写入1表示对EINT0使用边沿触发,反之,写入0表示对EINT0使用电平触发。
第1位:功能和上面相似只是对EINT1进行配置
第2位:是对EINT2进行配置
第3位:是对EINT3进行配置
第4~7位:保留
Eg;EXTMODE = 1<<3; // 设置EINT3中断为边沿触发模式
EXTMODE = 0<<3; // 设置EINT3中断为电平触发模式
3第三部外部中断还要对外部中断极性寄存器进行配置(EXTPOLAR)进行配置(在电平触发方式中,EXTPOLAR寄存器用来选择相应引脚是高电平或低电平有效。在边沿触发方式中,EXTPOLAR寄存器用来选择引脚上升沿或下降沿有效)
A EXTPOLAT(外部中断极性寄存器)总共有8位
第0位:是对EINT0进行配置,对该位写入1表示时表示
EINT0高电平或上升沿有效。反之,对该位写入0表示表示EINT0低电平或下降沿有效
第1位:是对EINT1进行配置。功能和上面类似。
第2位:是对EINT2进行配置。功能和上面类似
第3位:是对EINT3进行配置。功能和上面类似
第4~7位:保留位。
Eg: EXTPOLAR = 0x00; // 设置EINT3中断为下降沿触发
EXTPOLAR = 0x00;// 设置EINT3中断为低电平有效
4.第四部配置中断选择寄存器VICIntSelect
功能和前面的类似
Eg; VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
5若外部中断为向量中断则对向量控制寄存器0~15(VICVectCntl0~15)
进行配置。若为非向量中断则此步骤可省掉。
Eg: VICVectCntl0 = 0x20|17; // 分配EINT3中断到向量中断0,0x20表示向量IRQ使能,1<<17表示EINT3在VIC通道17号
6配置外部中断服务程序的地址:
a.若为向量中断则配置向量地址寄存器(VICVectAddrx)
a. b.若为非向量中断则配置默认向量地址寄存器VICDefVectAddr
eg: VICVectAddr0 = (int)IRQ_Eint3; // 设置向量中断服务程序地址IRQ_Eint3(为函数名,可随意起)
VICDefVectAddr = (int)IRQ_Eint3; // 设置非向量中断服务程序地址
7.清除外部中断标志
切记要在初始化时对EXTINT进行初始化。否则程序会进入异常。
配置外部中断标志寄存器(EXTINT)
A. 通过对EXINT寄存器写人1来将其清零来清除外部中断标志
B. EXTINT总共有8位
第0位:是对EINT0进行配置,写入1对外部中断EINT0中断进行清除
第1位:是对EINT1进行配置,写入1对外部中断EINT1中断进行清除。
第2位:是对EINT2进行配置,写入1对外部中断EINT2中断进行清除。
第3位:是对EINT3进行配置,写入1对外部中断EINT3中断进行清除。
第4~7位:保留位.
Eg: EXTINT = 1<<3; // 清除EINT3中断标志
8.对中断使能寄存器(VICIntEnable)进行配置
功能和前面说的类似
Eg: VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在VIC通道17号
注:编写外部中断程序时初始化实例:
1.初始化外部中断3,用向量中断,为边沿触发。
PINSEL1 = 3<<8; // 设置管脚连接,P0.20设置为EINT3
EXTMODE = 1<<3; // 设置EINT3中断为边沿触发模式
EXTPOLAR = 0x00; // 设置EINT3中断为下降沿触发
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICVectCntl0 = 0x20|17; // 分配EINT3中断到向量中断0
VICVectAddr0 = (int)IRQ_Eint3; // 设置中断服务程序地址
EXTINT = 1<<3; // 清除EINT3中断标志 ,次步不能少
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在VIC通道17号
2. 初始化外部中断为EINT3,用非向量中断,为电平触发
PINSEL1 = 3<<8; // 设置管脚连接,P0.20设置为EINT3
EXTMODE = 0<<3; // 设置EINT3中断为电平触发模式
EXTPOLAR = 0x00; // 设置EINT3中断为低电平触发
VICIntSelect = 0x00000000;// 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Eint3; // 设置中断服务程序地址
EXTINT = 1<<3; // 清除EINT3中断标志 ,次步不能少
VICIntEnable = 1<<17; //使能EINT3中断,EINT3在VIC通道17号
注:1.在编写中断服务函数时,外部中断为电平触发和边沿触发有区别
3. 在zlg模版中编写中断服务函数时,函数名的前缀是 __irq
函数实例:
1>用外部中断3,用向量中断,为边沿触发的中断服务函数的程序
void __irq IRQ_Eint3(void)
{
uint32 i;
i = IO0SET; // 读取当前B1控制值
if( (i&BEEPCON)==0 ) // 控制B1输出取反
{
IO0SET = BEEPCON;
}
else
{
IO0CLR = BEEPCON;
}
EXTINT = 1<<3; // 清除EINT3中断标志,1<<3 等价于 0x08
VICVectAddr = 0; // 向量中断结束
}
此中断函数实现的功能时当有按键按下时会蜂鸣。
注:1.每个中断服务函数的函数名前缀必须加__irq
2在中断服务程序最后要清除中断标志EXTINT = 1<<3,以及给VICVectAddr寄存器写入0;
3.切记在初始化外部中断时也要对EXTINT引脚进行初始化,否则程序会出现异常。
2>初始化外部中断为EINT3,用非向量中断,为电平触发
void __irq IRQ_Eint3(void)
{
uint32 i;
i = IO0SET; // 读取当前B1控制值
if( (i&BEEPCON)==0 ) // 控制B1输出取反
{
IO0SET = BEEPCON;
}
else
{
IO0CLR = BEEPCON;
}
/* 等待外部中断信号恢复为高电平(若信号保持为低电平,中断标志会一直置位) */
while( (EXTINT&1<<3)!=0 )
{
EXTINT = 1<<3; // 清除EINT3中断标志,
}
VICVectAddr = 0; // 向量中断结束
}
John哥说明:
在用电平触发时在中断服务程序最后要清除中断标志时,要使用
while( (EXTINT&1<<3)!=0 )
{
EXTINT = 1<<3; // 清除EINT3中断标志,
}
(因为等待外部中断信号恢复为高电平(若信号保持为低电平,中断标志会一直置位)这一点和边沿触发有区别。
注:
1.中断使能清零寄存器VICIntEnClr:那1位置1,则用来屏蔽该位的中断。
2. 当有多个中断源被设置为非向量IRQ中断时,需要在用户程序中识别中断源,并分别作出处理。所以非向量IRQ中断响应延时相对较长。
3. 中断状态寄存器:
a.如果使用了多个非向量IRQ中断或多个FIQ中断,那么在发生中断后要在程序中查找中断源。通过IRQ状态寄存器和FIQ状态寄存器可以了解到这些中断源的中断请求状态。
b. 任何在VIC中使能的中断都会把中断请求反映在“所有中断寄存器(VICRawIntr)中
c.所有中断状态寄存器(VICRawIntr):当某位为1时表示对应位的中断源产生中断请求。
d.FIQ状态寄存器(VICFIQStatus):当某位为1时表示对应位的中断产生FIQ中断请求。
e.IRQ状态寄存器(VICIRQStatus):当某位为1时表示对应位的中断源产生IRQ中断请求