"); //-->
作者:下家山(请尊重原创,转载请注明:上海索漫科技培训教材http://www.xiajiashan.com )
我们这里以LPC2136为例。
Lpc2136中有22个中断源,中断控制器提供了16个向量IRQ控制器,分别可以设置16个中断优先级!
其实,要真正体现中断优先级(当低优先级中断服务程序正在执行时,高优先级中断事件到来了,先执行高优先级中断服务程序代码,即高优先级中断会中断低优先级中断服务程序),必须实现中断嵌套!
很多裸奔的arm7或者arm9产品,并没有做中断嵌套,这种产品存在着隐患,而这种隐患常让工程师(开发或维护)无法解释!所以,就出现了,客户把有问题的产品拿到原厂,原厂却说在他哪里是好的,并且当场测试却怎么也测试不出来!
==================================================
假设,我们这里有两个外部中断
EINT1==KEY1===P0.3和EINT3===KEY3====P0.30
而且,我们这里EINT3的中断优先级高于EINT1
当EINT1正在执行的时候,EINT3来了,按照惯例,EINT1会停下来,去执行EINT3的中断,等EINT3的中断服务程序执行完毕,再回头执行EINT1的服务程序。如果我们不用中断嵌套,事情并非如此。
下面是实验代码:
#define KEY1 1<<3
#define KEY3 1<<30
#define LED1 1<<16
#define EINT1_NUM 15
#define EINT3_NUM 17
#define P03_FUN_EINT1 3<<6
#define P030_FUN_EINT3 2<<28
#define EINT1_ENABLE 1<<15
#define EINT3_ENABLE 1<<17
/******************************************
【By 下家山 Q群 75303301 上海松江文汇路928号258室 松江大学城
上海索漫科技 http://www.xiajiashan.com 专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训】***********/
void __irq IRQ_Eint3(void)
{
while(1)
{
IO0SET = BEEPCON;
}
EXTINT = 1<<3; // 清除EINT3中断标志,
VICVectAddr=0x00; // 清除中断逻辑,
}
/*===============================================*/
void __irq IRQ_Eint1(void)
{
while(1){
IO1CLR = LED1;
}
EXTINT = 1<<1; // 清除EINT3中断标志,
VICVectAddr=0x00; // 清除中断逻辑
}
/*************************************************************/
void Init_EXT(void)
{
PINSEL0 = P03_FUN_EINT1 | P030_FUN_EINT3; // 设置管脚连接,P0.3设置为EINT1, P0.30设置为EINT3
EXTMODE |= 1<<3; // 设置EINT3中断为边沿触发模式
EXTPOLAR &= ~(1<<3);// 设置EINT3中断为上升沿触发模式
EXTMODE |= 1<<1; // 设置EINT1中断为边沿触发模式
EXTPOLAR &= ~(1<<1);// 设置EINT1中断为上升沿触发模式
EXTINT = 0xF;
VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断
VICVectAddr0 = (uint32)IRQ_Eint3; // 设置中断服务程序地址向量
VICVectCntl0 = 0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)
VICVectAddr1 = (uint32)IRQ_Eint1; // 设置中断服务程序地址向量
VICVectCntl1 = 0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)
VICIntEnable = EINT1_ENABLE | EINT3_ENABLE; // 使能EINT1&EINT3中断,EINT3在Bit17,EINT1在bit15上
}
=======================================================================================
By 下家山 Q群 75303301 上海松江文汇路928号258室 松江大学城
上海索漫科技 http://www.xiajiashan.com 专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训 /*************************************/
void BEEFON(void)
{
IO0SET =BEEPCON;
}
/*************************************/
void BEEFOFF(void)
{
IO0CLR =BEEPCON;
}
/*************************************/
void init_system()
{
IO0CLR = BEEPCON;
IO0DIR = BEEPCON;
IO1SET = LED1;
IO1DIR = LED1 ;
}
/*************************************/
int main (void)
{
init_system();
Init_EINT();
while(1);
return 0;
}
上述程序执行结果是,我们先按下KEY1,LED1会亮,当我们再按下KEY3时,蜂鸣器并不会响。
=========================================================================================================================================================改成中断嵌套=======================================================================================================================================================================
#define KEY1 1<<3
#define KEY3 1<<30
#define LED1 1<<16
#define EINT1_NUM 15
#define EINT3_NUM 17
#define P03_FUN_EINT1 3<<6
#define P030_FUN_EINT3 2<<28
#define EINT1_ENABLE 1<<15
#define EINT3_ENABLE 1<<17
/*************************************/
__inline void enable_IRQ(void)
{
int tmp;
__asm
{
MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
/*************************************/
/*****************************************************/
void __irq IRQ_Eint3(void)
{
uint32 vic_enable_bak;
vic_enable_bak = VICIntEnable;
VICIntEnClr = (EINT3_ENABLE) | (EINT1_ENABLE); //清除自己及比自己优先级更低的中断,以便更高优先级中断响应
VICVectAddr=0x00; // 清除中断逻辑,
while(1)
{
IO0SET = BEEPCON;
}
EXTINT = 1<<3; // 清除EINT3中断标志,
VICIntEnable = vic_enable_bak;//恢复中断
}
=======================================================================================
By 下家山 Q群 75303301 上海松江文汇路928号258室 松江大学城
上海索漫科技 http://www.xiajiashan.com 专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训 /*===============================================*/
void __irq IRQ_Eint1(void)
{
uint32 vic_enable_bak;
vic_enable_bak = VICIntEnable;
VICIntEnClr = EINT1_ENABLE;//清除自己以便更高优先级中断响应
VICVectAddr=0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
enable_IRQ();
while(1){//一般不会在中断服务程序里面做死循环,但为了更好说明问题使然。
IO1CLR = LED1;
}
EXTINT = 1<<1; // 清除EINT3中断标志,
VICIntEnable = vic_enable_bak; //恢复中断
}
/*************************************************************/
void Init_EXT(void)
{
PINSEL0 = P03_FUN_EINT1 | P030_FUN_EINT3; // 设置管脚连接,P0.3设置为EINT1, P0.30设置为EINT3
EXTMODE |= 1<<3; // 设置EINT3中断为边沿触发模式
EXTPOLAR &= ~(1<<3);// 设置EINT3中断为上升沿触发模式
EXTMODE |= 1<<1; // 设置EINT1中断为边沿触发模式
EXTPOLAR &= ~(1<<1);// 设置EINT1中断为上升沿触发模式
EXTINT = 0xF;
VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断
VICVectAddr0 = (uint32)IRQ_Eint3; // 设置中断服务程序地址向量
VICVectCntl0 = 0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)
VICVectAddr1 = (uint32)IRQ_Eint1; // 设置中断服务程序地址向量
VICVectCntl1 = 0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)
VICIntEnable = EINT1_ENABLE | EINT3_ENABLE; // 使能EINT1&EINT3中断,EINT3在Bit17,EINT1在bit15上
}
/*************************************/
void BEEFON(void)
{
IO0SET =BEEPCON;
}
/*************************************/
void BEEFOFF(void)
{
IO0CLR =BEEPCON;
}
/*************************************/
void init_system()
{
IO0CLR = BEEPCON;
IO0DIR = BEEPCON;
IO1SET = LED1;
IO1DIR = LED1 ;
}
/*************************************/
int main (void)
{
init_system();
Init_EINT();
while(1);
return 0;
}
上述程序执行结果是,我们先按下KEY1,LED1会亮,当我们再按下KEY3时,即使EINT1中断进入了死循环,因为正确设置了中断嵌套,EINT3可以中断EINT1的服务程序运行自己的中断服务程序,蜂鸣器会响。
写于上海松江
作者:下家山(请尊重原创, 转载请注明) http://www.xiajiashan.com,有什么问题可与我联系:ximenpiaoxue4016@sina.com
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
针对LED照明应用的安森美半导体电源驱动解决方案
捷希凯选择飞思卡尔XS110芯片组开发UWB miniPCI 模块
4小时的交流电源定时器(555、BH4024)
绿色能源趋势和对电源转换的影响
如何设计超宽输入电压范围反激式变换器
差分磁电流传感和位置传感
爱发科发布多款半导体制造利器,引领先进制程技术革新
一种简单易制的抢答器
一种另类的键盘扩展方法
使用NXP MCX W71无线MCU保护您的资产
一种实用的微机硬币鉴别装置
GAIO推出适用于飞思卡尔汽车微控制器的支持包
乘用车不可或缺的电池管理系统BMS
DEK晶圆凸起和焊球置放解决方案以更低单位封装成本提供更高产量
高可靠通用定时器(CC4518、CC4001)
HUBER+SUHNER推出优质户外光纤连接器
一种控制步进电机转速的方法
DEK用于TIM涂敷的高精度批量挤压印刷工艺提升材料的均匀性和可靠性
由MC14541构成的简单定时器
意法半导体65W GaN变换器为注重成本的应用提供节省空间的电源方案
用于前沿小型太阳能与通信电源系统的高能效方案
非汽车BMS的功能安全设计
一种快速精确的捷联惯导系统初始对准方法研究
TE Connectivity调研揭示:不同国家人工智能时代的到来不一致
电饭锅预置断电定时器
AGI时代AI全新思维
用于零电压开关结构的新一代高电压CoolMOS
采用CD4060B构成的高可靠通用定时器
贸泽开售适用于工业自动化、机器人和智慧农业应用的Analog Devices ADIS1657x MEMS IMU模块
创新的液晶电视LED背光驱动解决方案