|
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 |
|
|