中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
作者:
标题: 求助DOS下的中断编程 上一主题 | 下一主题
caohuitong
新手上路





积分 12
发帖 5
注册 2008-9-23
状态 离线
『楼 主』:  求助DOS下的中断编程

定时器中断服务程序,怎么修改定时器的定时时间呢?
即怎么样才能使某一段代码在预定的时间间隔内被invoke(调用)。
我现在的办法是setvect(0x1c,myfunc),这样myfunc每秒被调用18.2次,怎么样修改这个调用频率呢?

[ Last edited by caohuitong on 2008-10-13 at 21:27 ]

2008-10-13 21:25
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
firstsail
高级用户





积分 668
发帖 295
注册 2005-7-26
来自 广东深圳
状态 离线
『第 2 楼』:  

typedef unsigned short WORD;

WORD wGlobal_SystemDivide  = 2;
WORD wGlobal_SystemCounter = 0;

//函数原型:void ChangeSystemTimer(WORD wDivide)
//函数作用:改变系统定时器
//入口参数:WORD wDivide ---- 分频数,取值在1~16之间
//         wDivide = 1时,每秒中断(18.2 * pow(2,1- 1)次,即54.94mS中断一次
//         wDivide = X时,每秒中断(18.2 * pow(2,X-1))次
//出口参数:无
//返 回 值:无


//传递参数时用"wGlobal_SystemDivide"全局变量
void ChangeSystemTimer(WORD wDivide)
{
        //时钟是1.1931817MHz
        //计算计数值
        WORD wTimer = (WORD)((65536L >> (wDivide - 1u)));

        //选择计数器0, 先低后高读/写入,模式3,二进制数计数
        asm mov al, 00110110B //36H
        asm out 43H, al       //选择模式
        asm mov ax, wTimer
        asm out 40H, Al       //写入低字节
        asm mov al, ah
        asm out 40H, Al       //写入高字节

        return;
}


//中断0x1C需要修改
void far interrupt NewInt1C()
{
     //在中断函数里面不要执行浮点运算,否则需要保护数学协处理器FCU,指令是FSave,FWait和frstor
   

        asm mov ax, seg wGlobal_SystemCounter
        asm mov ds, ax


        if ((++wGlobal_SystemCounter) >= (1 <<  (wGlobal_SystemDivide - 1)))
        {
                wGlobal_SystemCounter = 0;
                //这里调用老的中断1CH
        }

                //这里执行您自己的函数
          //...
        return;
}

//需要修改老的delay函数
void NewDelay(WORD wMilloSeconds)
{
        for (int i = 0; i < (1 <<  (wGlobal_SystemDivide - 1)); i++)
        {
                                //这里有错,以后修改
                ::delay(wMilloSeconds);
        }
}

[ Last edited by firstsail on 2008-10-14 at 11:23 ]

2008-10-14 10:37
查看资料  访问主页  发短消息 网志   编辑帖子  回复  引用回复
firstsail
高级用户





积分 668
发帖 295
注册 2005-7-26
来自 广东深圳
状态 离线
『第 3 楼』:  bc31的delay函数源代码

/*---------------------------------------------------------------------------
* filename - delay.cas
*
* function(s)
*        delay - wait for specified period.
*--------------------------------------------------------------------------*/

/*
*      C/C++ Run Time Library - Version 5.0
*
*      Copyright (c) 1987, 1992 by Borland International
*      All Rights Reserved.
*
*/


#pragma inline
#include <asmrules.h>
#include <dos.h>

static unsigned long multiplier = 1193*2L;

static void near dummy (void) {}

/*--------------------------------------------------------------------------*

Name            readtimer - read the complemented value of timer 0

Usage           unsigned readtimer (void);

Prototype in    local

Description     Obtain the complement of the value in timer 0.  The
                complement is used so that the timer will appear to
                count up rather than down.  The value returned will
                range from 0 to 0xffff.

Return value    The complement of the value in timer 0.

*---------------------------------------------------------------------------*/

static unsigned near readtimer (void)
{
  asm pushf                    /* Save interrupt flag                       */
  asm cli                      /* Disable interrupts                        */
  asm mov  al,0h               /* Latch timer 0                             */
  asm out  43h,al
      dummy();                 /* Waste some time */
  asm in   al,40h              /* Counter --> bx                            */
  asm mov  bl,al               /* LSB in BL                                 */
      dummy();                 /* Waste some time */
  asm in   al,40h
  asm mov  bh,al               /* MSB in BH                                 */
  asm not  bx                  /* Need ascending counter                    */
  asm popf                     /* Restore interrupt flag                    */
  return( _BX );
}

/*--------------------------------------------------------------------------*

Name            timer_init - initialize multiplier for delay function

Usage           void timer_init (void);

Prototype in    local

Description     Determine the multiplier required to convert milliseconds
                to an equivalent interval timer value.  Interval timer 0
                is normally programmed in mode 3 (square wave), where
                the timer is decremented by two every 840 nanoseconds;
                in this case the multiplier is 2386.  However, some
                programs and device drivers reprogram the timer in mode 2,
                where the timer is decremented by one every 840 ns; in this
                case the multiplier is halved, i.e. 1193.

                When the timer is in mode 3, it will never have an odd value.
                In mode 2, the timer can have both odd and even values.
                Therefore, if we read the timer 100 times and never
                see an odd value, it's a pretty safe assumption that
                it's in mode 3.  This is the method used in timer_init.

Return value    None

*---------------------------------------------------------------------------*/

static void timer_init(void)
{
    int i;

    for (i = 0; i < 100; i++)
        if ((readtimer() & 1) == 0)     /* readtimer() returns complement */
            {
            multiplier = 1193L;
            return;
            }
}

#pragma startup timer_init 16

/*--------------------------------------------------------------------------*

Name            delay - wait for specified period.

Usage           void delay(unsigned milliseconds);

Prototype in    dos.h

Description     The current thread of execution is suspended for the specified
                number of milliseconds.

Return value    None
*---------------------------------------------------------------------------*/

void _CType delay( unsigned milliseconds )
{
    unsigned long stop;
    unsigned cur, prev;

    stop = (prev = readtimer()) + (milliseconds * multiplier);

    while ((cur = readtimer()) < stop)
        {
        if (cur < prev)     /* Check for timer wraparound */
            {
            if (stop < 0x10000L)
                break;
            stop -= 0x10000L;
            }
        prev = cur;
        }
}

2008-10-14 10:47
查看资料  访问主页  发短消息 网志   编辑帖子  回复  引用回复
caohuitong
新手上路





积分 12
发帖 5
注册 2008-9-23
状态 离线
『第 4 楼』:  Thanks

今天在Turbo C/C++ 3.0 编译环境中试了一下,代码运行正常(但我也没有对delay进行修改)。ChangeSystemTimer是可以运行的。

2008-10-16 09:42
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: