阅读:1724回复:10
晕菜,IRQ问题放在Kernel区没人理,特请教:
我用一个脉冲发生器作为硬件中断源,直接接到IRQ2的接口上。
然后利用IRQ2中断去记数,代码如下: #include <conio.h> #include <dos.h> #include <bios.h> #include <stdio.h> #define INTR 0x0a // IRQ2 这里对否? #ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif void interrupt ( *oldtimehandler)(__CPPARGS); void interrupt timehandler(__CPPARGS); long int time_clock=0; char flag=0; void main() { clrscr(); //清屏 oldtimehandler = getvect(INTR); //保存环境变量 setvect(INTR, timehandler); //设定中断 while(bioskey(1)==0){ //若有键按下则推出 if(flag==1){ //若接收到新的中断则打印提示 printf(\" %i\",time_clock); //打印提示 flag=0; //中断标志置0 } } } void interrupt timehandler(__CPPARGS) { disable(); //关中断 time_clock++; //计数器加一 oldtimehandler(); //恢复原中断环境 outportb(0x20,0x20); //硬件中断结束 enable(); //开中断 flag=1; //中断标志置1 } 经实验,在IRQ2的接口上可以检测到信号,但计数器的值没有变化。 那么是不是我的代码什么地方还有问题? :( :( :( :( |
|
|
沙发#
发布于:2002-11-16 13:23
1.说明白你用的os.
2.在使用某个中断时,应该将其对应使能(8259) 代码如下: int mask = inportb(0x21); mask = mask & ~(1<<interrupt_line); outportb(0x21,mask); 3.记忆中,irql2被用作slave 8259. 4.现在用这玩艺的不多了,已经忘记了(岁月如梭)... |
|
板凳#
发布于:2002-11-16 15:29
1.说明白你用的os. 我的软件是在DOS6.22下使用,语言是BC31。除了两个串口没有其他的什么I/O口。 那么我上面的代码,将 #define INTR 0x0a 改成: #define INTR 0x1C 就可以接收到系统的时钟中断(每秒18.2次的中断)。 那么不使用IRQ2,而使用IRQ10,或IRQ11,这句话该怎么写? #define INTR ??? //应该添什么?他和IRQi的对应关系如何? :( 另外 mask = mask & ~(1<<interrupt_line); 一句中的interrupt_line应该如何理解? [编辑 - 11/16/02 by rudolf] |
|
|
地板#
发布于:2002-11-16 16:23
多谢dazzy老大的指点。问题已经解决了一半。
根据你的提示,我在网上查找到了一篇介绍IRQ11使用的例子(http://www.gjwtech.com/scomm/sc8259ainitial.htm)。根据例子已经可以接收到中断了。但是仍然不知道里面的具体的奥妙。故我将例子铁出来不懂的地方,请各位老大再指点一二。 #include <conio.h> #include <dos.h> #include <bios.h> #include <stdio.h> #define INTR 0x73 // IRQ11 问题1:在这IRQi 和INTR的对应关系如何?我用IRQ2是否应该对应0x10? #ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif void interrupt ( *OldIrq)(__CPPARGS); void interrupt NewIrq(__CPPARGS); unsigned long int Counter=0; char flag=0; void main() { int temp; clrscr(); //清屏 OldIrq = getvect(INTR); //保存环境变量 setvect(INTR,NewIrq); //设定中断 temp = inportb(0x21) & 0xFB; //打开主片IRQ2 outportb(0x21, temp); temp = inportb(0xA1) & 0xF7; //打开从片IRQ11 outportb(0xA1, temp); /*问题2:在这里分别打开了主从片,那么是否是主片IRQ2对应0xFB从片IRQ11对应0xF7。如果我使用IRQ10,则0xF7应该对应什么?IRQ2呢?*/ printf(\"Begin(%i): \\n\",INTR); while(bioskey(1)==0){ //若有键按下则推出 if(flag==1&&(Counter%1000==0)){ //若接收到新的中断则打印提示 printf(\" %lu\",Counter); //打印提示 flag=0; //中断标志置0 } } printf(\"LUCKEY!\"); setvect(0x73, OldIrq); //恢复原中断向量 temp = inportb(0x21) | ~(0xFB); //关主片IRQ2 outportb(0x21, temp); temp = inportb(0xA1) | ~(0xF7); //关从片IRQ11 outportb(0xA1, temp); } void interrupt NewIrq(__CPPARGS) { disable(); //关中断 Counter++; //计数器加一 outportb(0xA0,0x20); //向从片ICR送EOI命令 outportb(0x20,0x20); //向主片ICR送EOI命令 enable(); //开中断 flag=1; //中断标志置1 } |
|
|
地下室#
发布于:2002-11-16 20:16
前几天刚好在DOS下调过一块板卡的中断,说一些心得吧:
1.IRQ2一般都用作主板上第二片8259的级联输入,不能随便用,其它很多中断跟计算机外设也有默认的对应关系。 2.中断号和中断相量的对应关系在硬件书上都有介绍,中断0-7对应的中断相量应该是中断号+8(比如用中断5,就要把INTR定义为13),中断8-15对应的中断相量从0x70开始。 3.设置中断相量前应该首先关中断,BC31里有DISABLE()函数,设置完再ENABLE()。 4.I/O口0x20、0x21和0xa0、0xa1分别对应两片8259,管理中断0-7和中断8-15,0x21和0xa1是8259的中断屏蔽字,某一位=0表示允许中断,=1表示屏蔽中断 5.你程序中“temp = inportb(0x21) | ~(0xFB); //关主片IRQ2”是不是把中断8-15全部屏蔽了,计算机的硬盘控制器还有很多其它的外设岂不是都不能正常工作了? 6.我觉得应该在测试程序开中断之前加入outportb(0x20,0x20)和outportb(0xA0,0x20),否则如果你在运行测试程序之前板卡已经向8259触发中断,会导致无法进入第一次中断,不知道这个说法对不对。 |
|
5楼#
发布于:2002-11-17 13:25
非常感谢EandE的心得。我还有几个问题要问:
第1点,那么EandE兄认为在没有其他板卡使用中断的情况下应该用哪个中断比较好呢? 第2点中,“比如用中断5,就要把INTR定义为13”那么相应的语句是否该这样写: OldIrq = getvect(0x13); //保存环境变量 setvect(0x13,NewIrq); //设定中断入口 那么为什么不是0x0D而是0x13呢(13对应的16进制数应该是0x0d啊)? 第4点,那么0x20和0x21的具体作用是什么呢? 我查了很多书,都没有提到要打开或关闭8259芯片,也没有提到这几个IO口地址的具体含义及用法 :( 第5点,“temp = inportb(0x21) | ~(0xFB); //关主片IRQ2”一句中在(0xFB)前有一个“~”应该是只屏蔽中断11吧。 第6点,我也同意。 |
|
|
6楼#
发布于:2002-11-17 16:57
if (yourIRQ >=8)
{ Vect = yourIRQ + 0x68; } else { vect = yourIRQ + 8; } disable(); old = getvect(Vect); setvect(Vect, yourISR); //enable interrupt ... enable(); ... |
|
7楼#
发布于:2002-11-18 08:34
if (yourIRQ >=8) 看来我在钻牛角尖嘛。 这样好了,哪位大大直接告诉我IRQ5在使用时应该如何写。 是: old = getvect(0x13); 还是 old = getvect(0x0d); 如果是0x13那么从IRQ0-IRQ7的对应关系是: IRQ0-0x08 IRQ1-0x09 IRQ2-0x10 //??? IRQ3-0x11 //??? IRQ4-0x12 //??? IRQ5-0x13 //??? IRQ6-0x14 //??? IRQ7-0x15 //??? 还是: IRQ0-0x08 IRQ1-0x09 IRQ2-0x0a //??? IRQ3-0x0b //??? IRQ4-0x0c //??? IRQ5-0x0d //??? IRQ6-0x0e //??? IRQ7-0x0f //??? 另外0x20和0x21的具体作用是什么呢? 望各位再次指点。 |
|
|
8楼#
发布于:2002-11-18 10:18
1.中断5对应的是10进制数13,用16进制表示就是0x0d。
2.我看的书上介绍中断8-15对应的中断相量是0x70-0x77,不是从0x68开始。 3.如果使用定时器中断(中断相量0x1c),或其它与8259无关的中断,就不必对8259的I/O口操作。 4计算机通常默认的中断设置我记得的有以下几个: IRQ0:定时器; IRQ1:键盘 IRQ2:8259级联; IRQ3:COM2; IRQ4:COM1; IRQ6:软驱; IRQ7:并口 IRQ12:PS2 IRQ14:PRIMARY IDE IRQ15:SECONDARY IDE |
|
9楼#
发布于:2002-11-18 11:29
1.中断5对应的是10进制数13,用16进制表示就是0x0d。 呵呵,终于明白了。 另外arthurtu大佬的例子没有写错, IRQ8是:8+0x68=0x70 哦,对了0x20和0x21呢?有没有人知道? |
|
|
10楼#
发布于:2002-11-18 12:39
呵呵,刚才是我看花眼了。
0x20和0x21的介绍随便找本计算机硬件基础的书,都有详细说明的,到图书馆找找去吧。 |
|