共2条
1/1 1 跳转至页
LPC2104 怎样调通LPC2104的外部中断!!!
问
经过3天的时间,终于调通了2104开发板的外部非向量中断。
我的开发板是esayARM2104,跑例子程序EINT1_test没有问题,而我自己用LPC21XX的工程模板建立的项目,把原来的EINT1_LED.c拷过来,编译,调试,却无法进入中断,在论坛上我发现很多人也遇到了同样的问题。
今天,我终于把这个程序给调通了,在此传上来供大家参考。注意:我的程序是在flsah中调试,所以没有进行remap,编译时必须选择DebugInFlash。
其实,LPC2104的非向量中断很简单,只是由于工程模板的启动代码和例子程序不一样,所以不能直接运行,要自己进行修改。
1. 首先要打开IRQ中断。就是cpsr的i为必须清零。这一步可以在InitStack里加上。
2. 要在自己的c程序EINT1_LED.c中加上对 VICDefVectAddr的赋值操作,制定中断服务程序的地址。
3. 要在中断服务程序的末尾对VICVectAddr清零,以便能够再次进入中断。
以下是经过修改的EINT1_LED.c程序:
/****************************************************************************
* File:EINT1_LED.C
* 功能:使用外部中断1进行LED4的控制,每当有一次中断时,即取反LED4,
* 以便指示中断输入。
* 说明:将跳线器JP8_LED4短接。
****************************************************************************/
#include "config.h"
#define LEDCON 0x00002000 /* P0.13引脚控制LED4,低电平点亮*/
/****************************************************************************
* 名称:IRQ_Eint1()
* 功能:外部中断EINT1服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_Eint1(void)
{ uint32 i;
i = VICIRQStatus; // 读出VICIRQStatus的值
i = IOSET; // 读取当前LED4控制值
if( (i&LEDCON)==0 ) // 控制LED4输出
{ IOSET = LEDCON;
}
else
{ IOCLR = LEDCON;
}
while( (EXTINT&0x02)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x02; // 清除EINT1中断标志
}
VICVectAddr=0;//清零,下次可以进入中断
}
/****************************************************************************
* 名称:main()
* 功能:初始化外部中断1及IO连接等。
****************************************************************************/
int main(void)
{ PINSEL0 = 0x20000000; // 设置I/O口工作模式,P0.14设置为EINT1
PINSEL1 = 0x00000000;
IODIR = LEDCON; // 设置LED4控制口为输出,其它I/O为输入
VICDefVectAddr=(int)IRQ_Eint1;//设置中断服务程序的地址
/* 打开EINT1中断(不设置向量控制器,即使用非向量IRQ) */
VICIntSelect = 0x00000000;
VICIntEnable = 0x00008000;
EXTINT = 0x07; // 清除外部中断标志
while(1); // 等待中断
return(0);
}
以下是修改过的启动代码Startup.s
;/****************************************Copyright (c)**************************************************
;** 广州周立功单片机发展有限公司
;** 研 究 所
;** 产品一部
;**
;** http://www.zlgmcu.com
;**
;**--------------文件信息--------------------------------------------------------------------------------
;**文 件 名: Startup.s
;**创 建 人: 陈明计
;**最后修改日期: 2004年3月3日
;**描 述: lpc21xx的启动代码,包含异常向量入口、初始化堆栈的代码等
;** 每个工程应当有独立的这个文件的拷贝,并进行相应的修改
;**--------------历史版本信息----------------------------------------------------------------------------
;** 创建人: 陈明计
;** 版 本: v1.0
;** 日 期: 2004年2月2日
;** 描 述: 原始版本
;**
;**------------------------------------------------------------------------------------------------------
;** 修改人:
;** 版 本:
;** 日 期:
;** 描 述:
;**
;**--------------当前版本修订------------------------------------------------------------------------------
;** 修改人:
;** 日 期:
;** 描 述:
;**
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
;定义堆栈的大小
SVC_STACK_LEGTH EQU 0
FIQ_STACK_LEGTH EQU 0
IRQ_STACK_LEGTH EQU 256
ABT_STACK_LEGTH EQU 0
UND_STACK_LEGTH EQU 0
NoInt EQU 0x80
USR32Mode EQU 0x10
SVC32Mode EQU 0x13
SYS32Mode EQU 0x1f
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
PINSEL2 EQU 0xE002C014
;引入的外部标号在这声明
IMPORT FIQ_Exception ;快速中断异常处理程序
IMPORT __main ;C语言主程序入口
IMPORT TargetResetInit ;目标板基本初始化
IMPORT StackUsr
IMPORT bottom_of_heap
;给外部使用的标号在这声明
EXPORT Reset
EXPORT __rt_div0
EXPORT __user_initial_stackheap
CODE32
AREA vectors,CODE,READONLY
ENTRY
;中断向量表
Reset
LDR PC, ResetAddr
LDR PC, UndefinedAddr
LDR PC, SWI_Addr
LDR PC, PrefetchAddr
LDR PC, DataAbortAddr
DCD 0xb9205f80
LDR PC, [PC, #-0xff0]
LDR PC, FIQ_Addr
ResetAddr DCD ResetInit
UndefinedAddr DCD Undefined
SWI_Addr DCD SoftwareInterrupt
PrefetchAddr DCD PrefetchAbort
DataAbortAddr DCD DataAbort
Nouse DCD 0
IRQ_Addr DCD 0
FIQ_Addr DCD FIQ_Handler
;未定义指令
Undefined
B Undefined
;软中断
SoftwareInterrupt
B SoftwareInterrupt
;取指令中止
PrefetchAbort
B PrefetchAbort
;取数据中止
DataAbort
B DataAbort
;快速中断
FIQ_Handler
STMFD SP!, {R0-R3, LR}
BL FIQ_Exception
LDMFD SP!, {R0-R3, LR}
SUBS PC, LR, #4
;/*********************************************************************************************************
;** 函数名称: InitStack
;** 功能描述: 初始化堆栈
;** 输 入: 无
;** 输 出 : 无
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修 改:
;** 日 期:
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
InitStack
MOV R0, LR
;设置管理模式堆栈
MSR CPSR_c, #0xd3
LDR SP, StackSvc
;设置中断模式堆栈
MSR CPSR_c, #0xd2
LDR SP, StackIrq
;设置快速中断模式堆栈
MSR CPSR_c, #0xd1
LDR SP, StackFiq
;设置中止模式堆栈
MSR CPSR_c, #0xd7
LDR SP, StackAbt
;设置未定义模式堆栈
MSR CPSR_c, #0xdb
LDR SP, StackUnd
;设置系统模式堆栈
MSR CPSR_c, #0xdf
LDR SP, =StackUsr
MSR CPSR_c,#0x1f ;这行程序使能IRQ中断,清零cpsr的I位
MOV PC, R0
;/*********************************************************************************************************
;** 函数名称: ResetInit
;** 功能描述: 复位入口
;**
;** 输 入: 无
;**
;** 输 出: 无
;**
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修改人: 陈明计
;** 日 期: 2004年3月3日
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
ResetInit
BL InitStack ;初始化堆栈
BL TargetResetInit ;目标板基本初始化
B __main ;跳转到c语言入口
;/*********************************************************************************************************
;** 函数名称: __user_initial_stackheap
;** 功能描述: 库函数初始化堆和栈,不能删除
;**
;** 输 入: 参考库函数手册
;**
;** 输 出: 参考库函数手册
;**
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修改人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
__user_initial_stackheap
LDR r0,=bottom_of_heap
MOV pc,lr
;/*********************************************************************************************************
;** 函数名称: __rt_div0
;** 功能描述: 整数除法除数为0错误处理函数,替代原始的__rt_div0减少目标代码大小
;**
;** 输 入: 参考库函数手册
;**
;** 输 出: 无
;**
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修改人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
__rt_div0
B __rt_div0
StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4
StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4
StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4
StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4
StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4
;/* 分配堆栈空间 */
AREA MyStacks, DATA, NOINIT, ALIGN=2
SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间
IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;中断模式堆栈空间
FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;快速中断模式堆栈空间
AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;中止义模式堆栈空间
UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;未定义模式堆栈
END
;/*********************************************************************************************************
;** End Of File
;********************************************************************************************************/
其他文件不需要改动。就可以了!!!
如果想在ram里调试,加上remap程序即可。
以上只是个人的一点心得,希望能让学习ARM的人少走些弯路。同时我也在学习ARM,希望大家共同进步!!!
答 1: 是在Vectors.s中修改吗?实在无奈,只好闯老帖子了!
我怎么编译都通不过?是在init.s还是 Vectors.s中修改
刚开始学ARM,还没能力自己写启动代码,在做这个试验时也遇到中断进不去的问题,希得到帮助!
我的开发板是esayARM2104,跑例子程序EINT1_test没有问题,而我自己用LPC21XX的工程模板建立的项目,把原来的EINT1_LED.c拷过来,编译,调试,却无法进入中断,在论坛上我发现很多人也遇到了同样的问题。
今天,我终于把这个程序给调通了,在此传上来供大家参考。注意:我的程序是在flsah中调试,所以没有进行remap,编译时必须选择DebugInFlash。
其实,LPC2104的非向量中断很简单,只是由于工程模板的启动代码和例子程序不一样,所以不能直接运行,要自己进行修改。
1. 首先要打开IRQ中断。就是cpsr的i为必须清零。这一步可以在InitStack里加上。
2. 要在自己的c程序EINT1_LED.c中加上对 VICDefVectAddr的赋值操作,制定中断服务程序的地址。
3. 要在中断服务程序的末尾对VICVectAddr清零,以便能够再次进入中断。
以下是经过修改的EINT1_LED.c程序:
/****************************************************************************
* File:EINT1_LED.C
* 功能:使用外部中断1进行LED4的控制,每当有一次中断时,即取反LED4,
* 以便指示中断输入。
* 说明:将跳线器JP8_LED4短接。
****************************************************************************/
#include "config.h"
#define LEDCON 0x00002000 /* P0.13引脚控制LED4,低电平点亮*/
/****************************************************************************
* 名称:IRQ_Eint1()
* 功能:外部中断EINT1服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_Eint1(void)
{ uint32 i;
i = VICIRQStatus; // 读出VICIRQStatus的值
i = IOSET; // 读取当前LED4控制值
if( (i&LEDCON)==0 ) // 控制LED4输出
{ IOSET = LEDCON;
}
else
{ IOCLR = LEDCON;
}
while( (EXTINT&0x02)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x02; // 清除EINT1中断标志
}
VICVectAddr=0;//清零,下次可以进入中断
}
/****************************************************************************
* 名称:main()
* 功能:初始化外部中断1及IO连接等。
****************************************************************************/
int main(void)
{ PINSEL0 = 0x20000000; // 设置I/O口工作模式,P0.14设置为EINT1
PINSEL1 = 0x00000000;
IODIR = LEDCON; // 设置LED4控制口为输出,其它I/O为输入
VICDefVectAddr=(int)IRQ_Eint1;//设置中断服务程序的地址
/* 打开EINT1中断(不设置向量控制器,即使用非向量IRQ) */
VICIntSelect = 0x00000000;
VICIntEnable = 0x00008000;
EXTINT = 0x07; // 清除外部中断标志
while(1); // 等待中断
return(0);
}
以下是修改过的启动代码Startup.s
;/****************************************Copyright (c)**************************************************
;** 广州周立功单片机发展有限公司
;** 研 究 所
;** 产品一部
;**
;** http://www.zlgmcu.com
;**
;**--------------文件信息--------------------------------------------------------------------------------
;**文 件 名: Startup.s
;**创 建 人: 陈明计
;**最后修改日期: 2004年3月3日
;**描 述: lpc21xx的启动代码,包含异常向量入口、初始化堆栈的代码等
;** 每个工程应当有独立的这个文件的拷贝,并进行相应的修改
;**--------------历史版本信息----------------------------------------------------------------------------
;** 创建人: 陈明计
;** 版 本: v1.0
;** 日 期: 2004年2月2日
;** 描 述: 原始版本
;**
;**------------------------------------------------------------------------------------------------------
;** 修改人:
;** 版 本:
;** 日 期:
;** 描 述:
;**
;**--------------当前版本修订------------------------------------------------------------------------------
;** 修改人:
;** 日 期:
;** 描 述:
;**
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
;定义堆栈的大小
SVC_STACK_LEGTH EQU 0
FIQ_STACK_LEGTH EQU 0
IRQ_STACK_LEGTH EQU 256
ABT_STACK_LEGTH EQU 0
UND_STACK_LEGTH EQU 0
NoInt EQU 0x80
USR32Mode EQU 0x10
SVC32Mode EQU 0x13
SYS32Mode EQU 0x1f
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
PINSEL2 EQU 0xE002C014
;引入的外部标号在这声明
IMPORT FIQ_Exception ;快速中断异常处理程序
IMPORT __main ;C语言主程序入口
IMPORT TargetResetInit ;目标板基本初始化
IMPORT StackUsr
IMPORT bottom_of_heap
;给外部使用的标号在这声明
EXPORT Reset
EXPORT __rt_div0
EXPORT __user_initial_stackheap
CODE32
AREA vectors,CODE,READONLY
ENTRY
;中断向量表
Reset
LDR PC, ResetAddr
LDR PC, UndefinedAddr
LDR PC, SWI_Addr
LDR PC, PrefetchAddr
LDR PC, DataAbortAddr
DCD 0xb9205f80
LDR PC, [PC, #-0xff0]
LDR PC, FIQ_Addr
ResetAddr DCD ResetInit
UndefinedAddr DCD Undefined
SWI_Addr DCD SoftwareInterrupt
PrefetchAddr DCD PrefetchAbort
DataAbortAddr DCD DataAbort
Nouse DCD 0
IRQ_Addr DCD 0
FIQ_Addr DCD FIQ_Handler
;未定义指令
Undefined
B Undefined
;软中断
SoftwareInterrupt
B SoftwareInterrupt
;取指令中止
PrefetchAbort
B PrefetchAbort
;取数据中止
DataAbort
B DataAbort
;快速中断
FIQ_Handler
STMFD SP!, {R0-R3, LR}
BL FIQ_Exception
LDMFD SP!, {R0-R3, LR}
SUBS PC, LR, #4
;/*********************************************************************************************************
;** 函数名称: InitStack
;** 功能描述: 初始化堆栈
;** 输 入: 无
;** 输 出 : 无
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修 改:
;** 日 期:
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
InitStack
MOV R0, LR
;设置管理模式堆栈
MSR CPSR_c, #0xd3
LDR SP, StackSvc
;设置中断模式堆栈
MSR CPSR_c, #0xd2
LDR SP, StackIrq
;设置快速中断模式堆栈
MSR CPSR_c, #0xd1
LDR SP, StackFiq
;设置中止模式堆栈
MSR CPSR_c, #0xd7
LDR SP, StackAbt
;设置未定义模式堆栈
MSR CPSR_c, #0xdb
LDR SP, StackUnd
;设置系统模式堆栈
MSR CPSR_c, #0xdf
LDR SP, =StackUsr
MSR CPSR_c,#0x1f ;这行程序使能IRQ中断,清零cpsr的I位
MOV PC, R0
;/*********************************************************************************************************
;** 函数名称: ResetInit
;** 功能描述: 复位入口
;**
;** 输 入: 无
;**
;** 输 出: 无
;**
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修改人: 陈明计
;** 日 期: 2004年3月3日
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
ResetInit
BL InitStack ;初始化堆栈
BL TargetResetInit ;目标板基本初始化
B __main ;跳转到c语言入口
;/*********************************************************************************************************
;** 函数名称: __user_initial_stackheap
;** 功能描述: 库函数初始化堆和栈,不能删除
;**
;** 输 入: 参考库函数手册
;**
;** 输 出: 参考库函数手册
;**
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修改人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
__user_initial_stackheap
LDR r0,=bottom_of_heap
MOV pc,lr
;/*********************************************************************************************************
;** 函数名称: __rt_div0
;** 功能描述: 整数除法除数为0错误处理函数,替代原始的__rt_div0减少目标代码大小
;**
;** 输 入: 参考库函数手册
;**
;** 输 出: 无
;**
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2004年2月2日
;**-------------------------------------------------------------------------------------------------------
;** 修改人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
__rt_div0
B __rt_div0
StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4
StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4
StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4
StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4
StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4
;/* 分配堆栈空间 */
AREA MyStacks, DATA, NOINIT, ALIGN=2
SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间
IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;中断模式堆栈空间
FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;快速中断模式堆栈空间
AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;中止义模式堆栈空间
UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;未定义模式堆栈
END
;/*********************************************************************************************************
;** End Of File
;********************************************************************************************************/
其他文件不需要改动。就可以了!!!
如果想在ram里调试,加上remap程序即可。
以上只是个人的一点心得,希望能让学习ARM的人少走些弯路。同时我也在学习ARM,希望大家共同进步!!!
答 1: 是在Vectors.s中修改吗?实在无奈,只好闯老帖子了!
我怎么编译都通不过?是在init.s还是 Vectors.s中修改
刚开始学ARM,还没能力自己写启动代码,在做这个试验时也遇到中断进不去的问题,希得到帮助!
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |