rudolf
驱动小牛
驱动小牛
  • 注册日期2002-10-09
  • 最后登录2006-04-25
  • 粉丝0
  • 关注0
  • 积分81分
  • 威望9点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
阅读:1724回复:10

晕菜,IRQ问题放在Kernel区没人理,特请教:

楼主#
更多 发布于:2002-11-16 09:31
我用一个脉冲发生器作为硬件中断源,直接接到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的接口上可以检测到信号,但计数器的值没有变化。
那么是不是我的代码什么地方还有问题?
 :( :( :( :(
靠天靠地靠父母,不如靠自己。
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
沙发#
发布于: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.现在用这玩艺的不多了,已经忘记了(岁月如梭)...
rudolf
驱动小牛
驱动小牛
  • 注册日期2002-10-09
  • 最后登录2006-04-25
  • 粉丝0
  • 关注0
  • 积分81分
  • 威望9点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-11-16 15:29
1.说明白你用的os.
2.在使用某个中断时,应该将其对应使能(8259)
代码如下:
int mask = inportb(0x21);
mask = mask & ~(1<<interrupt_line);
outportb(0x21,mask);
3.记忆中,irql2被用作slave 8259.
4.现在用这玩艺的不多了,已经忘记了(岁月如梭)...


我的软件是在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]
靠天靠地靠父母,不如靠自己。
rudolf
驱动小牛
驱动小牛
  • 注册日期2002-10-09
  • 最后登录2006-04-25
  • 粉丝0
  • 关注0
  • 积分81分
  • 威望9点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
地板#
发布于: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
}

 
靠天靠地靠父母,不如靠自己。
EandE
驱动牛犊
驱动牛犊
  • 注册日期2002-10-21
  • 最后登录2003-10-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于: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触发中断,会导致无法进入第一次中断,不知道这个说法对不对。
rudolf
驱动小牛
驱动小牛
  • 注册日期2002-10-09
  • 最后登录2006-04-25
  • 粉丝0
  • 关注0
  • 积分81分
  • 威望9点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
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点,我也同意。
靠天靠地靠父母,不如靠自己。
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
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();
...
rudolf
驱动小牛
驱动小牛
  • 注册日期2002-10-09
  • 最后登录2006-04-25
  • 粉丝0
  • 关注0
  • 积分81分
  • 威望9点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-11-18 08:34
if (yourIRQ >=8)
{
  Vect = yourIRQ + 0x68;
}
else
{
  vect = yourIRQ + 8;
}
disable();
old = getvect(Vect);
setvect(Vect, yourISR);
//enable interrupt
...
enable();
...


看来我在钻牛角尖嘛。
这样好了,哪位大大直接告诉我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的具体作用是什么呢?
望各位再次指点。
靠天靠地靠父母,不如靠自己。
EandE
驱动牛犊
驱动牛犊
  • 注册日期2002-10-21
  • 最后登录2003-10-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
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


rudolf
驱动小牛
驱动小牛
  • 注册日期2002-10-09
  • 最后登录2006-04-25
  • 粉丝0
  • 关注0
  • 积分81分
  • 威望9点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-11-18 11:29
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


 


呵呵,终于明白了。
另外arthurtu大佬的例子没有写错,
IRQ8是:8+0x68=0x70

哦,对了0x20和0x21呢?有没有人知道?
靠天靠地靠父母,不如靠自己。
EandE
驱动牛犊
驱动牛犊
  • 注册日期2002-10-21
  • 最后登录2003-10-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-11-18 12:39
呵呵,刚才是我看花眼了。
0x20和0x21的介绍随便找本计算机硬件基础的书,都有详细说明的,到图书馆找找去吧。
游客

返回顶部