共2条
1/1 1 跳转至页
UCOS 在UCOS中,编了一个中断嵌套的试验程序,试验结果不对,请帮忙!
问
ARM芯片 : LPC2124
目的 :任务1就是一个由定时器0控制的LED闪程序,观察
与外部中断2嵌套后,两个LED的现象。
程序如下 :
/*
main.c
*/
#include "config.h"
#include "stdlib.h"
#define TaskStkLengh 64 //Define the Task0 stack length 定义用户任务0的堆栈长度
//试验代码
#define LED1CON 0x00000010 //P0.4_P27为LED1控制端
#define LED2CON 0x00000020 //P0.5_P29为LED2控制端
OS_STK TaskStk0 [TaskStkLengh];
void Task0(void *pdata); //Task0 任务0
/****************************************************************************
* 名称:EnableIRQ()
* 功能:打开IRQ中断允许。
* 入口参数:无
* 出口参数:无
****************************************************************************/
__inline void EnableIRQ(void)
{ int tmp;
__asm
{ MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
int main (void)
{
PINSEL0 = 0x0000C000; //引脚连接设置,P0.0,P0.1为串口,P0.7_P31为EINT2
PINSEL1 = 0x00000000;
PINSEL2 = 0x00000000;
IO0DIR = LED1CON|LED2CON;
OSInit ();
OSTaskCreate (Task0,(void *)0, &TaskStk0[TaskStkLengh - 1], 2);
OSStart ();
return 0;
}
/*********************************************************************************************************
** Task0 任务0
********************************************************************************************************/
void Task0 (void *pdata)
{
pdata = pdata;
TargetInit ();
while (1)
{
if(0==(IO0SET&LED1CON)) IO0SET = LED1CON; //点亮LED
else IO0CLR = LED1CON;
OSTimeDly(30);
}
}
/****************************************************************************
* 名称:IRQ_Eint3()
* 功能:外部中断EINT3服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint2(void)
{ uint32 i, bak;
bak = VICIntEnable;
VICIntEnClr = (1<<16);
VICVectAddr = 0x00;
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED4控制值
if( (i&LED2CON)==0 ) // 控制LED4输出
{ IO0SET = LED2CON;
}
else
{ IO0CLR = LED2CON;
}
while( (EXTINT&0x04)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x04; // 清除EINT3中断标志
}
VICIntEnable = bak;
}
/*
target.c
*/
void VICInit(void)
{
extern void IRQ_Handler(void);
extern void Timer0_Handler(void);
extern void Eint2_Handler(void); //**添加用户代码**
extern void Uart0_Handler(void);
VICIntEnClr = 0xffffffff;
VICDefVectAddr = (uint32)IRQ_Handler;
VICVectAddr0 = (uint32)Timer0_Handler;
VICVectCntl0 = (0x20 | 0x04);
VICVectAddr2 = (uint32)Eint2_Handler; //**添加用户代码**
VICVectCntl2 = (0x20 | 0x10); //**添加用户代码**
EXTMODE = 0x04; //设置EINT2为边沿触发
EXTPOLAR = 0x00;
VICIntEnable = 1<<4;
VICIntEnable = 1<<16; //**添加用户代码**
}
void TargetInit(void)
{
OS_ENTER_CRITICAL();
srand((uint32) TargetInit);
VICInit();
Timer0Init();
Eint2Init();
OS_EXIT_CRITICAL();
}
/*
IRQ.S
*/
INCLUDE irq.inc ; Inport the head file 引入头文件
CODE32
AREA IRQ,CODE,READONLY
;/* 以下添加中断句柄,用户根据实际情况改变 */
;/* Add interrupt handler here,user could change it as needed */
;/*中断*/
;/*Interrupt*/
IRQ_Handler HANDLER IRQ_Exception
;/*定时器0中断*/
;/*Time0 Interrupt*/
Timer0_Handler HANDLER Timer0_Exception
;/*外部中断2*/
;/*EINT0 Interrupt*/
Eint2_Handler HANDLER IRQ_Eint2
试验现象是 :
当按键按下不放时,中断控制的LED和定时器控制的LED同步闪烁,我认为应该是中断控制的LED不变,定时器控制的LED不间断的闪烁.
请问问题出在什么地方? 答 1: 没道理外部中断2控制的LED2会闪!我已经在中断初始化函数(VICInit())中将EINT2设置为下边沿触发,这样,当按住按键不放的情况下,不会在触发中断啦!外部中断服务子程序就不会执行,LED2也就不可能闪啊!可它闪个不停!请大家帮忙看看! 答 2: 请周工帮忙分析一下吧!回答问题的大侠少了! 答 3: 这个问题困扰我好几天啦!解决不了的话,解决不了的话,后面的应用程序开发就没戏啦!有条件的朋友帮忙跑一下程序,看看问题出在哪里?人多力量大啊!先谢谢支持的朋友啦!谢谢! 答 4: 中断嵌套比较麻烦,不做过多技术支持。仅给一个例子: void UART0_Exception(void)
{
uint8 IIR, temp, i;
VICIntEnClr = (1 << 6) | (1 << 4);
VICVectAddr = 0; // 通知中断控制器中断结束
OS_ENTER_CRITICAL();
OS_EXIT_CRITICAL();
while(((IIR = U0IIR) & 0x01) == 0)
{ /* 有中断未处理完 */
switch (IIR & 0x0e)
{
case 0x02: /* THRE中断 */
for (i = 0; i < UART0_FIFO_LENGTH; i++) /* 向发送FIFO填充数据 */
{
if (QueueRead(&temp, UART0SendBuf) == QUEUE_OK)
{
U0THR = temp;
}
else
{
U0IER = U0IER & (~0x02); /* 队列空,则禁止发送中断 */
}
}
break;
case 0x04: /* 接收数据可用 */
OSSemPost(Uart0Sem); /* 通知接收任务 */
U0IER = U0IER & (~0x01); /* 禁止接收及字符超时中断 */
break;
case 0x06: /* 接收线状态 */
temp = U0LSR;
break;
case 0x0c: /* 字符超时指示 */
OSSemPost(Uart0Sem); /* 通知接收任务 */
U0IER = U0IER & (~0x01); /* 禁止接收及字符超时中断 */
break;
default :
break;
}
}
VICIntEnable = (1 << 6) | (1 << 4);
}
void Timer0_Exception(void)
{
VICIntEnClr = 1 << 4;
VICVectAddr = 0; // 通知中断控制器中断结束
OS_ENTER_CRITICAL();
OS_EXIT_CRITICAL();
T0IR = 0x01;
OSTimeTick();
VICIntEnable = 1 << 4;
}
void VICInit(void)
{
extern void IRQ_Handler(void);
extern void Timer0_Handler(void);
extern void UART0_Handler(void);
VICIntEnClr = 0xffffffff;
VICDefVectAddr = (uint32)IRQ_Handler;
VICVectAddr14 = (uint32)UART0_Handler;
VICVectCntl14 = (0x20 | 0x06);
VICIntEnable = 1 << 6;
VICVectAddr15 = (uint32)Timer0_Handler;
VICVectCntl15 = (0x20 | 0x04);
VICIntEnable = 1 << 4;
}
答 5: 再问一下!UCOSII中肯定要用一个定时中断作为时钟节拍,如果加上键盘扫描使用一个外部中断,定时中断不能停,是不是就一定要中断嵌套,在定时中断中嵌套外部中断,还是外部中断嵌套定时中断?我认为是后者,在外部中断中开定时器中断?
还有就是你还没指出我的程序哪里不对呀! 答 6: 留下QQ,有愿意讨论中断嵌套的朋友请加入。408709006 答 7: 不明白还是要问!我在你们网站上下载了一段中断嵌套的程序,在板上运行挺正常,可是改了部分程序就出现问题:
源程序
/****************************************************************************
* 文件名:EINT03_VECT.C
* 功能:使能外部中断0和外部中断3,当外部中断0有效时,控制LED1取反;当外部中断3有效时,
* 控制取反LED4。使用向量中断方式。
* 说明:将跳线器JP4_LED1、JP4_LED4短接,然后按下/放开KEY1,使EINT0为低/高电平;按
* 下/放开KEY5,使EINT3为低/高电平。
*
*****************已更改,允许IRQ中断嵌套*****************
****************************************************************************/
#include "config.h"
#define LED1CON (1<<22) /* P0.22口为LED1控制端 */
#define LED4CON (1<<25) /* P0.25口为LED4控制端 */
void Eint0_Handler(void);
void Eint3_Handler(void);
/****************************************************************************
* 名称:EnableIRQ()
* 功能:打开IRQ中断允许。
* 入口参数:无
* 出口参数:无
****************************************************************************/
__inline void EnableIRQ(void)
{ int tmp;
__asm
{ MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
/****************************************************************************
* 名称:IRQ_Eint0()
* 功能:外部中断EINT0服务函数,取反LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint0(void)
{ uint32 i, bak;
bak = VICIntEnable; // 备份当前VICIntEnable的值
VICIntEnClr = (1<<14)|(1<<17); // 禁止当前优先级中断及低优先级中断
VICVectAddr = 0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED1控制值
if( (i&LED1CON)==0 ) // 控制LED1输出
{ IO0SET = LED1CON;
}
else
{ IO0CLR = LED1CON;
}
while( (EXTINT&0x01)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x01; // 清除EINT0中断标志
}
VICIntEnable = bak;
}
/****************************************************************************
* 名称:IRQ_Eint3()
* 功能:外部中断EINT3服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint3(void)
{ uint32 i, bak;
bak = VICIntEnable;
VICIntEnClr = (1<<17);
VICVectAddr = 0x00;
EnableIRQ();
i = IO0SET; // 读取当前LED4控制值
if( (i&LED4CON)==0 ) // 控制LED4输出
{ IO0SET = LED4CON;
}
else
{ IO0CLR = LED4CON;
}
while( (EXTINT&0x08)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x08; // 清除EINT3中断标志
}
VICIntEnable = bak;
}
/****************************************************************************
* 名称:main()
* 功能:初始化外部中断0、3为向量中断,并设置为下降沿触发模式,然后等待外部中断。
* 说明:在STARTUP.S文件中使能IRQ中断(清零CPSR中的I位)。
****************************************************************************/
int main(void)
{ PINSEL0 = 0x00000000;
PINSEL1 = 0x00000301; // 设置管脚连接,P0.16设置为EINT0,P0.20设置为EINT3
IO0DIR = LED1CON|LED4CON; // 设置B1控制口为输出,其它I/O为输入
/* 打开EINT0、EINT3中断(设置向量控制器,即使用向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICVectCntl0 = 0x20|14; // 分配EINT0中断到向量中断0
VICVectAddr0 = (int)Eint0_Handler; // 设置中断服务程序地址
VICVectCntl1 = 0x20|17; // 分配EINT3中断到向量中断1
VICVectAddr1 = (int)Eint3_Handler; // 设置中断服务程序地址
EXTINT = 0x09; // 清除EINT0、EINT3中断标志
VICIntEnable = (1<<14)|(1<<17); // 使能EINT0、EINT3中断
EnableIRQ();
while(1); // 等待中断
return(0);
}
修改后的程序
/****************************************************************************
* 文件名:EINT03_VECT.C
* 功能:使能外部中断0和外部中断3,当外部中断0有效时,控制LED1取反;当外部中断3有效时,
* 控制取反LED4。使用向量中断方式。
* 说明:将跳线器JP4_LED1、JP4_LED4短接,然后按下/放开KEY1,使EINT0为低/高电平;按
* 下/放开KEY5,使EINT3为低/高电平。
*
*****************已更改,允许IRQ中断嵌套*****************
****************************************************************************/
#include "config.h"
#define LED1CON (1<<4) /* P0.22口为LED1控制端 */
#define LED4CON (1<<5) /* P0.25口为LED4控制端 */
void Eint0_Handler(void);
void Eint2_Handler(void);
void Timer0_Handler(void);
/****************************************************************************
* 名称:EnableIRQ()
* 功能:打开IRQ中断允许。
* 入口参数:无
* 出口参数:无
****************************************************************************/
__inline void EnableIRQ(void)
{ int tmp;
__asm
{ MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
/****************************************************************************
* 名称:IRQ_Time0()
* 功能:外部中断EINT0服务函数,取反LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Timer0(void)
{ uint32 i, bak;
bak = VICIntEnable; // 备份当前VICIntEnable的值
VICIntEnClr = (1<<4)|(1<<16); // 禁止当前优先级中断及低优先级中断
VICVectAddr = 0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED1控制值
if( (i&LED1CON)==0 ) // 控制LED1输出
{ IO0SET = LED1CON;
}
else
{ IO0CLR = LED1CON;
}
T0IR = 0x01;
VICIntEnable = bak;
}
/****************************************************************************
* 名称:IRQ_Eint0()
* 功能:外部中断EINT0服务函数,取反LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint0(void)
{ uint32 i, bak;
bak = VICIntEnable; // 备份当前VICIntEnable的值
VICIntEnClr = (1<<14)|(1<<16); // 禁止当前优先级中断及低优先级中断
VICVectAddr = 0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED1控制值
if( (i&LED1CON)==0 ) // 控制LED1输出
{ IO0SET = LED1CON;
}
else
{ IO0CLR = LED1CON;
}
while( (EXTINT&0x01)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x01; // 清除EINT0中断标志
}
VICIntEnable = bak;
}
/****************************************************************************
* 名称:IRQ_Eint3()
* 功能:外部中断EINT3服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint2(void)
{ uint32 i,bak;
bak = VICIntEnable;
VICIntEnClr = (1<<16);
VICVectAddr = 0x00;
EnableIRQ();
i = IO0SET; // 读取当前LED4控制值
if( (i&LED4CON)==0 ) // 控制LED4输出
{ IO0SET = LED4CON;
}
else
{ IO0CLR = LED4CON;
}
while( (EXTINT&0x04)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x04; // 清除EINT3中断标志
}
EXTINT = 0x04;
VICIntEnable = bak;
}
/****************************************************************************
* 名称:main()
* 功能:初始化外部中断0、3为向量中断,并设置为下降沿触发模式,然后等待外部中断。
* 说明:在STARTUP.S文件中使能IRQ中断(清零CPSR中的I位)。
****************************************************************************/
int main(void)
{ PINSEL0 = 0x0000C000;
PINSEL1 = 0x00000000; // 设置管脚连接,P0.1设置为EINT0,P0.7设置为EINT2
PINSEL2 = 0x00000000;
IO0DIR = LED1CON|LED4CON; // 设置B1控制口为输出,其它I/O为输入
/* 打开EINT0、EINT3中断(设置向量控制器,即使用向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
T0PR = 99;
T0MCR = 0x03;
T0MR0 = 110592/2;
T0IR = 0xffffffff;
T0TC = 0;
T0TCR = 0x03;
T0TCR = 0x01;
//VICVectCntl0 = 0x20|14; // 分配EINT0中断到向量中断0
//VICVectAddr0 = (int)Eint0_Handler; // 设置中断服务程序地址
VICVectCntl0 = 0x20|4; // 分配TIMER0中断到向量中断0
VICVectAddr0 = (int)Timer0_Handler; //设置中断服务程序地址
VICVectCntl1 = 0x20|16; // 分配EINT2中断到向量中断1
VICVectAddr1 = (int)Eint2_Handler; // 设置中断服务程序地址
EXTINT = 0x04; // 清除EINT0、EINT2中断标志
EXTMODE = 0x04; //置外部中断0和2为边沿触发方式
VICIntEnable = (1<<4)|(1<<16); // 使能EINT0、EINT2中断
EnableIRQ();
while(1); // 等待中断
return(0);
}
可以看出源程序是两个外部中断0和2嵌套,在EINT2中打开EINT0,KEY1控制EINT0,KEY2控制EINT2,板子上的现象是,按住KEY1,键KEY2多次动作只被记住一次,按住KEY2,键KEY1动作不受影响.
修改后的程序运行结果理论上是,在EINT2中开TIMER0中断,按住KEY时,EINT2控制的LED不闪,TIMER0控制的LED闪,可我实际看到的是它们同时闪,EINT2已经被我设定为下边沿触发,当按下KEY不放时EINT2应该只中断一次,即LED亮或灭一次,并保持不动啊!WHY? 答 8: 总结。经过多次的试验,发现将外部中断改为电平触发,结果正常.
在EINT2中开TIMER0中断. 答 9: 该贴 一定要顶
目的 :任务1就是一个由定时器0控制的LED闪程序,观察
与外部中断2嵌套后,两个LED的现象。
程序如下 :
/*
main.c
*/
#include "config.h"
#include "stdlib.h"
#define TaskStkLengh 64 //Define the Task0 stack length 定义用户任务0的堆栈长度
//试验代码
#define LED1CON 0x00000010 //P0.4_P27为LED1控制端
#define LED2CON 0x00000020 //P0.5_P29为LED2控制端
OS_STK TaskStk0 [TaskStkLengh];
void Task0(void *pdata); //Task0 任务0
/****************************************************************************
* 名称:EnableIRQ()
* 功能:打开IRQ中断允许。
* 入口参数:无
* 出口参数:无
****************************************************************************/
__inline void EnableIRQ(void)
{ int tmp;
__asm
{ MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
int main (void)
{
PINSEL0 = 0x0000C000; //引脚连接设置,P0.0,P0.1为串口,P0.7_P31为EINT2
PINSEL1 = 0x00000000;
PINSEL2 = 0x00000000;
IO0DIR = LED1CON|LED2CON;
OSInit ();
OSTaskCreate (Task0,(void *)0, &TaskStk0[TaskStkLengh - 1], 2);
OSStart ();
return 0;
}
/*********************************************************************************************************
** Task0 任务0
********************************************************************************************************/
void Task0 (void *pdata)
{
pdata = pdata;
TargetInit ();
while (1)
{
if(0==(IO0SET&LED1CON)) IO0SET = LED1CON; //点亮LED
else IO0CLR = LED1CON;
OSTimeDly(30);
}
}
/****************************************************************************
* 名称:IRQ_Eint3()
* 功能:外部中断EINT3服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint2(void)
{ uint32 i, bak;
bak = VICIntEnable;
VICIntEnClr = (1<<16);
VICVectAddr = 0x00;
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED4控制值
if( (i&LED2CON)==0 ) // 控制LED4输出
{ IO0SET = LED2CON;
}
else
{ IO0CLR = LED2CON;
}
while( (EXTINT&0x04)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x04; // 清除EINT3中断标志
}
VICIntEnable = bak;
}
/*
target.c
*/
void VICInit(void)
{
extern void IRQ_Handler(void);
extern void Timer0_Handler(void);
extern void Eint2_Handler(void); //**添加用户代码**
extern void Uart0_Handler(void);
VICIntEnClr = 0xffffffff;
VICDefVectAddr = (uint32)IRQ_Handler;
VICVectAddr0 = (uint32)Timer0_Handler;
VICVectCntl0 = (0x20 | 0x04);
VICVectAddr2 = (uint32)Eint2_Handler; //**添加用户代码**
VICVectCntl2 = (0x20 | 0x10); //**添加用户代码**
EXTMODE = 0x04; //设置EINT2为边沿触发
EXTPOLAR = 0x00;
VICIntEnable = 1<<4;
VICIntEnable = 1<<16; //**添加用户代码**
}
void TargetInit(void)
{
OS_ENTER_CRITICAL();
srand((uint32) TargetInit);
VICInit();
Timer0Init();
Eint2Init();
OS_EXIT_CRITICAL();
}
/*
IRQ.S
*/
INCLUDE irq.inc ; Inport the head file 引入头文件
CODE32
AREA IRQ,CODE,READONLY
;/* 以下添加中断句柄,用户根据实际情况改变 */
;/* Add interrupt handler here,user could change it as needed */
;/*中断*/
;/*Interrupt*/
IRQ_Handler HANDLER IRQ_Exception
;/*定时器0中断*/
;/*Time0 Interrupt*/
Timer0_Handler HANDLER Timer0_Exception
;/*外部中断2*/
;/*EINT0 Interrupt*/
Eint2_Handler HANDLER IRQ_Eint2
试验现象是 :
当按键按下不放时,中断控制的LED和定时器控制的LED同步闪烁,我认为应该是中断控制的LED不变,定时器控制的LED不间断的闪烁.
请问问题出在什么地方? 答 1: 没道理外部中断2控制的LED2会闪!我已经在中断初始化函数(VICInit())中将EINT2设置为下边沿触发,这样,当按住按键不放的情况下,不会在触发中断啦!外部中断服务子程序就不会执行,LED2也就不可能闪啊!可它闪个不停!请大家帮忙看看! 答 2: 请周工帮忙分析一下吧!回答问题的大侠少了! 答 3: 这个问题困扰我好几天啦!解决不了的话,解决不了的话,后面的应用程序开发就没戏啦!有条件的朋友帮忙跑一下程序,看看问题出在哪里?人多力量大啊!先谢谢支持的朋友啦!谢谢! 答 4: 中断嵌套比较麻烦,不做过多技术支持。仅给一个例子: void UART0_Exception(void)
{
uint8 IIR, temp, i;
VICIntEnClr = (1 << 6) | (1 << 4);
VICVectAddr = 0; // 通知中断控制器中断结束
OS_ENTER_CRITICAL();
OS_EXIT_CRITICAL();
while(((IIR = U0IIR) & 0x01) == 0)
{ /* 有中断未处理完 */
switch (IIR & 0x0e)
{
case 0x02: /* THRE中断 */
for (i = 0; i < UART0_FIFO_LENGTH; i++) /* 向发送FIFO填充数据 */
{
if (QueueRead(&temp, UART0SendBuf) == QUEUE_OK)
{
U0THR = temp;
}
else
{
U0IER = U0IER & (~0x02); /* 队列空,则禁止发送中断 */
}
}
break;
case 0x04: /* 接收数据可用 */
OSSemPost(Uart0Sem); /* 通知接收任务 */
U0IER = U0IER & (~0x01); /* 禁止接收及字符超时中断 */
break;
case 0x06: /* 接收线状态 */
temp = U0LSR;
break;
case 0x0c: /* 字符超时指示 */
OSSemPost(Uart0Sem); /* 通知接收任务 */
U0IER = U0IER & (~0x01); /* 禁止接收及字符超时中断 */
break;
default :
break;
}
}
VICIntEnable = (1 << 6) | (1 << 4);
}
void Timer0_Exception(void)
{
VICIntEnClr = 1 << 4;
VICVectAddr = 0; // 通知中断控制器中断结束
OS_ENTER_CRITICAL();
OS_EXIT_CRITICAL();
T0IR = 0x01;
OSTimeTick();
VICIntEnable = 1 << 4;
}
void VICInit(void)
{
extern void IRQ_Handler(void);
extern void Timer0_Handler(void);
extern void UART0_Handler(void);
VICIntEnClr = 0xffffffff;
VICDefVectAddr = (uint32)IRQ_Handler;
VICVectAddr14 = (uint32)UART0_Handler;
VICVectCntl14 = (0x20 | 0x06);
VICIntEnable = 1 << 6;
VICVectAddr15 = (uint32)Timer0_Handler;
VICVectCntl15 = (0x20 | 0x04);
VICIntEnable = 1 << 4;
}
答 5: 再问一下!UCOSII中肯定要用一个定时中断作为时钟节拍,如果加上键盘扫描使用一个外部中断,定时中断不能停,是不是就一定要中断嵌套,在定时中断中嵌套外部中断,还是外部中断嵌套定时中断?我认为是后者,在外部中断中开定时器中断?
还有就是你还没指出我的程序哪里不对呀! 答 6: 留下QQ,有愿意讨论中断嵌套的朋友请加入。408709006 答 7: 不明白还是要问!我在你们网站上下载了一段中断嵌套的程序,在板上运行挺正常,可是改了部分程序就出现问题:
源程序
/****************************************************************************
* 文件名:EINT03_VECT.C
* 功能:使能外部中断0和外部中断3,当外部中断0有效时,控制LED1取反;当外部中断3有效时,
* 控制取反LED4。使用向量中断方式。
* 说明:将跳线器JP4_LED1、JP4_LED4短接,然后按下/放开KEY1,使EINT0为低/高电平;按
* 下/放开KEY5,使EINT3为低/高电平。
*
*****************已更改,允许IRQ中断嵌套*****************
****************************************************************************/
#include "config.h"
#define LED1CON (1<<22) /* P0.22口为LED1控制端 */
#define LED4CON (1<<25) /* P0.25口为LED4控制端 */
void Eint0_Handler(void);
void Eint3_Handler(void);
/****************************************************************************
* 名称:EnableIRQ()
* 功能:打开IRQ中断允许。
* 入口参数:无
* 出口参数:无
****************************************************************************/
__inline void EnableIRQ(void)
{ int tmp;
__asm
{ MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
/****************************************************************************
* 名称:IRQ_Eint0()
* 功能:外部中断EINT0服务函数,取反LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint0(void)
{ uint32 i, bak;
bak = VICIntEnable; // 备份当前VICIntEnable的值
VICIntEnClr = (1<<14)|(1<<17); // 禁止当前优先级中断及低优先级中断
VICVectAddr = 0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED1控制值
if( (i&LED1CON)==0 ) // 控制LED1输出
{ IO0SET = LED1CON;
}
else
{ IO0CLR = LED1CON;
}
while( (EXTINT&0x01)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x01; // 清除EINT0中断标志
}
VICIntEnable = bak;
}
/****************************************************************************
* 名称:IRQ_Eint3()
* 功能:外部中断EINT3服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint3(void)
{ uint32 i, bak;
bak = VICIntEnable;
VICIntEnClr = (1<<17);
VICVectAddr = 0x00;
EnableIRQ();
i = IO0SET; // 读取当前LED4控制值
if( (i&LED4CON)==0 ) // 控制LED4输出
{ IO0SET = LED4CON;
}
else
{ IO0CLR = LED4CON;
}
while( (EXTINT&0x08)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x08; // 清除EINT3中断标志
}
VICIntEnable = bak;
}
/****************************************************************************
* 名称:main()
* 功能:初始化外部中断0、3为向量中断,并设置为下降沿触发模式,然后等待外部中断。
* 说明:在STARTUP.S文件中使能IRQ中断(清零CPSR中的I位)。
****************************************************************************/
int main(void)
{ PINSEL0 = 0x00000000;
PINSEL1 = 0x00000301; // 设置管脚连接,P0.16设置为EINT0,P0.20设置为EINT3
IO0DIR = LED1CON|LED4CON; // 设置B1控制口为输出,其它I/O为输入
/* 打开EINT0、EINT3中断(设置向量控制器,即使用向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICVectCntl0 = 0x20|14; // 分配EINT0中断到向量中断0
VICVectAddr0 = (int)Eint0_Handler; // 设置中断服务程序地址
VICVectCntl1 = 0x20|17; // 分配EINT3中断到向量中断1
VICVectAddr1 = (int)Eint3_Handler; // 设置中断服务程序地址
EXTINT = 0x09; // 清除EINT0、EINT3中断标志
VICIntEnable = (1<<14)|(1<<17); // 使能EINT0、EINT3中断
EnableIRQ();
while(1); // 等待中断
return(0);
}
修改后的程序
/****************************************************************************
* 文件名:EINT03_VECT.C
* 功能:使能外部中断0和外部中断3,当外部中断0有效时,控制LED1取反;当外部中断3有效时,
* 控制取反LED4。使用向量中断方式。
* 说明:将跳线器JP4_LED1、JP4_LED4短接,然后按下/放开KEY1,使EINT0为低/高电平;按
* 下/放开KEY5,使EINT3为低/高电平。
*
*****************已更改,允许IRQ中断嵌套*****************
****************************************************************************/
#include "config.h"
#define LED1CON (1<<4) /* P0.22口为LED1控制端 */
#define LED4CON (1<<5) /* P0.25口为LED4控制端 */
void Eint0_Handler(void);
void Eint2_Handler(void);
void Timer0_Handler(void);
/****************************************************************************
* 名称:EnableIRQ()
* 功能:打开IRQ中断允许。
* 入口参数:无
* 出口参数:无
****************************************************************************/
__inline void EnableIRQ(void)
{ int tmp;
__asm
{ MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
/****************************************************************************
* 名称:IRQ_Time0()
* 功能:外部中断EINT0服务函数,取反LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Timer0(void)
{ uint32 i, bak;
bak = VICIntEnable; // 备份当前VICIntEnable的值
VICIntEnClr = (1<<4)|(1<<16); // 禁止当前优先级中断及低优先级中断
VICVectAddr = 0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED1控制值
if( (i&LED1CON)==0 ) // 控制LED1输出
{ IO0SET = LED1CON;
}
else
{ IO0CLR = LED1CON;
}
T0IR = 0x01;
VICIntEnable = bak;
}
/****************************************************************************
* 名称:IRQ_Eint0()
* 功能:外部中断EINT0服务函数,取反LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint0(void)
{ uint32 i, bak;
bak = VICIntEnable; // 备份当前VICIntEnable的值
VICIntEnClr = (1<<14)|(1<<16); // 禁止当前优先级中断及低优先级中断
VICVectAddr = 0x00; // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
EnableIRQ(); // 打开IRQ中断允许
i = IO0SET; // 读取当前LED1控制值
if( (i&LED1CON)==0 ) // 控制LED1输出
{ IO0SET = LED1CON;
}
else
{ IO0CLR = LED1CON;
}
while( (EXTINT&0x01)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x01; // 清除EINT0中断标志
}
VICIntEnable = bak;
}
/****************************************************************************
* 名称:IRQ_Eint3()
* 功能:外部中断EINT3服务函数,取反LED4。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void IRQ_Eint2(void)
{ uint32 i,bak;
bak = VICIntEnable;
VICIntEnClr = (1<<16);
VICVectAddr = 0x00;
EnableIRQ();
i = IO0SET; // 读取当前LED4控制值
if( (i&LED4CON)==0 ) // 控制LED4输出
{ IO0SET = LED4CON;
}
else
{ IO0CLR = LED4CON;
}
while( (EXTINT&0x04)!=0 ) // 等待外部中断信号恢复为高电平
{ EXTINT = 0x04; // 清除EINT3中断标志
}
EXTINT = 0x04;
VICIntEnable = bak;
}
/****************************************************************************
* 名称:main()
* 功能:初始化外部中断0、3为向量中断,并设置为下降沿触发模式,然后等待外部中断。
* 说明:在STARTUP.S文件中使能IRQ中断(清零CPSR中的I位)。
****************************************************************************/
int main(void)
{ PINSEL0 = 0x0000C000;
PINSEL1 = 0x00000000; // 设置管脚连接,P0.1设置为EINT0,P0.7设置为EINT2
PINSEL2 = 0x00000000;
IO0DIR = LED1CON|LED4CON; // 设置B1控制口为输出,其它I/O为输入
/* 打开EINT0、EINT3中断(设置向量控制器,即使用向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
T0PR = 99;
T0MCR = 0x03;
T0MR0 = 110592/2;
T0IR = 0xffffffff;
T0TC = 0;
T0TCR = 0x03;
T0TCR = 0x01;
//VICVectCntl0 = 0x20|14; // 分配EINT0中断到向量中断0
//VICVectAddr0 = (int)Eint0_Handler; // 设置中断服务程序地址
VICVectCntl0 = 0x20|4; // 分配TIMER0中断到向量中断0
VICVectAddr0 = (int)Timer0_Handler; //设置中断服务程序地址
VICVectCntl1 = 0x20|16; // 分配EINT2中断到向量中断1
VICVectAddr1 = (int)Eint2_Handler; // 设置中断服务程序地址
EXTINT = 0x04; // 清除EINT0、EINT2中断标志
EXTMODE = 0x04; //置外部中断0和2为边沿触发方式
VICIntEnable = (1<<4)|(1<<16); // 使能EINT0、EINT2中断
EnableIRQ();
while(1); // 等待中断
return(0);
}
可以看出源程序是两个外部中断0和2嵌套,在EINT2中打开EINT0,KEY1控制EINT0,KEY2控制EINT2,板子上的现象是,按住KEY1,键KEY2多次动作只被记住一次,按住KEY2,键KEY1动作不受影响.
修改后的程序运行结果理论上是,在EINT2中开TIMER0中断,按住KEY时,EINT2控制的LED不闪,TIMER0控制的LED闪,可我实际看到的是它们同时闪,EINT2已经被我设定为下边沿触发,当按下KEY不放时EINT2应该只中断一次,即LED亮或灭一次,并保持不动啊!WHY? 答 8: 总结。经过多次的试验,发现将外部中断改为电平触发,结果正常.
在EINT2中开TIMER0中断. 答 9: 该贴 一定要顶
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |