![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-10-31 22:00 |
共 47,815 主题排行 / 349,930 发帖 / 今日 0 篇 / 48,290 会员排行 |
| DOS开发编程 & 发展交流 (开发室) » 一直存在的疑问:PC上8253计时器的精确频率到底是多少? |
| 可打印版本 1,848 / 11 |
| 第1楼 zyl910 | 发表于 2006-06-03 12:40 |
| 中级用户 发帖 126 积分 282 | |
|
一直存在的疑问:PC上8253计时器的精确频率到底是多少? PC机上8253计时器芯片的精确的输入频率到底是多少?
很多书上说PC机的8253的计时器#0的输出频率是每秒18.2次(每隔55ms触发一次),但都说这个只是约值,精确值有很长一串小数。计算机应该是靠整数运算的,那些小数值应该只是换算成现实时间的结果。所以我想知道精确的频率,于是查找了大量的资料,结果发现都有一点出入: 1.许多书上所说的(计数器#0)精确值: F: 每秒18.2064819336次 T: 每隔54.925ms。 2.Terrv Dettmann《DOS Programmer's Reference》: H: 由系统时钟每秒大约调用18.2次(每小时65536次)。 D: int 1Ah的00h功能: 该中断获取系统时钟计数器,该计数器从零点开始,每秒计数18.2065次。从零点(midnight)开始的一整天共需计86400秒,这段时间内的计数次数(时钟计数1573040次,经过的时间为86399.9129秒)。 3.Mazid《汇编语言、设计与接口技术》:8284芯片连接到一个14.31818MHz的晶振源,输出的Clr引脚是(8088中)CPU、内存(系统总线)的主频,1/3分频,4.772776MHz。PClk接8253/54计时器,1/6分频,2.386383MHz。在8284与8253之间存在一个72LS175的D触发器,所以频率又除以了2,1.1931817MHz。 4.在某些接口技术的书上说晶振源的频率周期是70ns,与内存速度匹配。 5.在很多计算机上,QueryPerformanceFrequency(Win32 API)的返回值是3579545。3579545 * 4 = 14318180,与3一致。 常数分析 ~~~~~~~~ 现在对这些常数进行计算分析: 第1种,根据频率(每秒18.2064819336次) 晶振源频率:18.2064819336Hz * 65536 * 12 = 14,318,160.0000049152Hz 周期:1s / 14,318,160.0000049152Hz = 0.000000069841376266200176256402804053989s = 69.841376266200176256402804053989ns 8253输入频率:18.2064819336Hz * 65536 = 1,193,180.0000004096Hz 周期:1s / 1,193,180.0000004096Hz = 0.00000083809651519440211507683364864787s = 838.09651519440211507683364864787ns 计时器#0输出频率:18.2064819336Hz 周期:1s / 18.2064819336Hz = 0.054925493219780337013675369997787s = 54.925493219780337013675369997787ms 计时器#0触发65536次:(1s / 18.2064819336Hz) * 65536 = 65536s / 18.2064819336Hz = 3599.597123651524166528229048175s 计时器#0触发1573040次:(1s / 18.2064819336Hz) * 1573040 = 1573040s / 18.2064819336Hz = 86399.997854443261335991904021318s 第1种,根据周期(每隔54.925ms) 晶振源频率:(1s / 54.925ms) * 65536 * 12 = (65536 * 12)s / 0.054925s = 14,318,288.575329995448338643604916Hz 周期:54.925ms / (65536 * 12) = 0.000000069840749104817708333333333333333s = 69.840749104817708333333333333333ns 8253输入频率:(1s / 54.925ms) * 65536 = 65536s / 0.054925s = 1,193,190.7146108329540282203004096Hz 周期:54.925ms / 65536 = 0.0000008380889892578125s = 838.0889892578125ns 计时器#0输出频率:1s / 54.925ms = 18.206645425580336822940373236231Hz 周期:54.925ms 计时器#0触发65536次:54.925ms * 65536 = 3599.5648s 计时器#0触发1573040次:54.925ms * 1573040 = 86399.222s 第2种,根据小时(每小时65536次) 晶振源频率:1s / (3600s / 65536 / 65536 / 12) = (65536 * 65536 * 12)s / 3600s = 14,316,557.653333333333333333333333Hz 周期:3600s / 65536 / 65536 / 12 = 3600s / (65536 * 65536 * 12) = 0.000000069849193096160888671875s = 69.849193096160888671875ns 8253输入频率:1s / (3600s / 65536 / 65536) = (65536*65536)s / 3600s = 1,193,046.4711111111111111111111111Hz 周期:3600s / 65536 / 65536 = 3600s / (65536 * 65536) = 0.0000008381903171539306640625s = 838.1903171539306640625ns 计时器#0输出频率:1s / (3600s / 65536) = 65536s / 3600s = 18.204444444444444444444444444444Hz 周期:3600s / 65536 = 0.054931640625s = 54.931640625ms 计时器#0触发65536次:3600s 计时器#0触发1573040次:(3600s / 65536) * 1573040 = (3600s * 1573040) / 65536 = 86409.66796875s 第2种,根据天(时钟计数1573040次,经过的时间为86399.9129秒) 晶振源频率:1s / (86399.9129s / 1573040 / 65536 / 12) = (1573040 * 65536 * 12)s / 86399.9129s = 14,318,174.078622248240715529702808Hz 周期:86399.9129s / 1573040 / 65536 / 12 = 86399.9129s / (1573040 * 65536 * 12) = 0.000000069841307593336928084579328349353s = 69.841307593336928084579328349353ns 8253输入频率:1s / (86399.9129s / 1573040 / 65536) = (1573040 * 65536)s / 86399.9129s = 1,193,181.1732185206867262941419007Hz 周期:86399.9129s / 1573040 / 65536 = 86399.9129s / (1573040 * 65536) = 0.00000083809569112004313701495194019224s = 838.09569112004313701495194019224ns 计时器#0输出频率:1s / (86399.9129s / 1573040) = 1573040s / 86399.9129s = 18.206499835487681377049165983592Hz 周期:86399.9129s / 1573040 = 0.054925439213243147027411890352439s = 54.925439213243147027411890352439ms 计时器#0触发65536次:(86399.9129s / 1573040) * 65536Hz = (86399.9129s * 65536) / 1573040 = 3599.5935842791028835884656461374s 计时器#0触发1573040次:86399.9129s 第3种(8284芯片连接到一个14.31818MHz的晶振源) 晶振源频率:14.31818MHz = 14,318,180Hz 周期:1s / 14,318,180Hz = 0.000000069841278710003645714748662190306s = 69.841278710003645714748662190306ns 8253输入频率:14,318,180Hz / 12 = 1,193,181.6666666666666666666666667Hz 周期:1s / (14,318,180Hz / 12) = 12s / 14,318,180Hz = 0.00000083809534452004374857698394628368s = 838.09534452004374857698394628368ns 计时器#0输出频率:14,318,180Hz / 12 / 65536 = 14,318,180Hz / (12 * 65536) = 18.206507364908854166666666666667Hz 周期:1s / (14,318,180Hz / 12 / 65536) = (12 * 65536)s / 14,318,180Hz = 0.054925416498465587106741219903647s = 54.925416498465587106741219903647ms 计时器#0触发65536次:(1s / (14,318,180Hz / 12 / 65536)) * 65536 = (12 * 65536 * 65536)s / 14,318,180Hz = 3599.5920956434407166273925876054s 计时器#0触发1573040次:(1s / (14,318,180Hz / 12 / 65536)) * 1573040 = (12 * 65536 * 1573040)s / 14,318,180Hz = 86399.877168746307142388208557233s 第4种(晶振源的频率周期是70ns,与内存速度匹配) 晶振源频率:1s / 0.00000007s = 14,285,714.285714285714285714285714Hz 周期:70ns = 0.00000007s 8253输入频率:1s / (0.00000007s * 12) = 1,190,476.1904761904761904761904762Hz 周期:0.00000007s * 12 = 0.00000084s = 840ns 计时器#0输出频率:1s / (0.00000007s * 12 * 65536) = 18.165225074404761904761904761905Hz 周期:0.00000007s * 12 * 65536 = 0.05505024s = 55.05024ms 计时器#0触发65536次:(0.00000007s * 12 * 65536) * 65536 = 3607.77252864s 计时器#0触发1573040次:(0.00000007s * 12 * 65536) * 1573040 = 86596.2295296s 总表 ~~~~ 晶振源频率(Hz): 1F: 14,318,160.0000049152 1T: 14,318,288.575329995448338643604916 2H: 14,316,557.653333333333333333333333 2D: 14,318,174.078622248240715529702808 3 : 14,318,180 4 : 14,285,714.285714285714285714285714 晶振源周期(ns): 1F: 69.841376266200176256402804053989 1T: 69.840749104817708333333333333333 2H: 69.849193096160888671875 2D: 69.841307593336928084579328349353 3 : 69.841278710003645714748662190306 4 : 70 8253输入频率(Hz): 1F: 1,193,180.0000004096 1T: 1,193,190.7146108329540282203004096 2H: 1,193,046.4711111111111111111111111 2D: 1,193,181.1732185206867262941419007 3 : 1,193,181.6666666666666666666666667 4 : 1,190,476.1904761904761904761904762 8253输入周期(ns): 1F: 838.09651519440211507683364864787 1T: 838.0889892578125 2H: 838.1903171539306640625 2D: 838.09569112004313701495194019224 3 : 838.09534452004374857698394628368 4 : 840 计时器#0输出频率(Hz): 1F: 18.2064819336 1T: 18.206645425580336822940373236231 2H: 18.204444444444444444444444444444 2D: 18.206499835487681377049165983592 3 : 18.206507364908854166666666666667 4 : 18.165225074404761904761904761905 计时器#0输出周期(ms): 1F: 54.925493219780337013675369997787 1T: 54.925 2H: 54.931640625 2D: 54.925439213243147027411890352439 3 : 54.925416498465587106741219903647 4 : 55.05024 计时器#0触发65536次(s): 1F: 3599.597123651524166528229048175 1T: 3599.5648 2H: 3600 2D: 3599.5935842791028835884656461374 3 : 3599.5920956434407166273925876054 4 : 3607.77252864 计时器#0触发1573040次(s): 1F: 86399.997854443261335991904021318 1T: 86399.222 2H: 86409.66796875 2D: 86399.9129 3 : 86399.877168746307142388208557233 4 : 86596.2295296 结论 ~~~~ 个人认为最可信的是《汇编语言、设计与接口技术》上的说法,晶振源频率为14,318,180Hz,因为它跟许多数字吻合。 PS: 我一直存在这个疑问,但是一直没有去研究。直到前两天看到风云的一篇文章《不太精准的时钟》(http://blog.codingnow.com/2006/05/iaeeoeo.html)后,才认识到这个问题的严重性,引起我关注这个问题。 [ Last edited by zyl910 on 2006-6-3 at 12:44 ] |
|
| 第2楼 Scott0902 | 发表于 2006-06-03 14:03 |
| 中级用户 发帖 237 积分 466 | |
|
深奥……
|
|
| 第3楼 zyl910 | 发表于 2006-06-03 14:27 |
| 中级用户 发帖 126 积分 282 | |
|
刚才又翻了一下《图形程序开发人员指南(Michael Abrash's Graphics Programming Black Book Special Editior)》的“Zen timer”,发现该代码采用的(输入频率周期)是0.8381ms(ZTimerReport函数):
以下是《图形程序开发人员指南》对8253的说明,与《汇编语言、设计与接口技术》一致:
|
|
| 第4楼 jawbin | 发表于 2006-06-08 19:29 |
| 高级用户 发帖 444 积分 994 | |
|
在通常的使用中,我就当是 18 次,没要求那么精密过. 可以设置成更高频率的( UCOS/II 好象就更改了),但是好象影响性能.
|
|
| 第5楼 fqljwdyq | 发表于 2006-06-09 08:15 |
| 新手上路 发帖 7 积分 14 来自 江苏 | |
|
其实在实际应用当中,精确定时从来不用系统提供的8253,一般用扩展卡中的定时,对系统的这个18.2秒不是太关心
|
|
| 第6楼 zyl910 | 发表于 2006-06-09 09:02 |
| 中级用户 发帖 126 积分 282 | |
|
但是我想在DOS下实现毫秒级定时啊!
是为了编动画、游戏程序 不可能希望别人装扩展卡 |
|
| 第7楼 zyl910 | 发表于 2006-06-09 09:08 |
| 中级用户 发帖 126 积分 282 | |
|
我的目的是:编写类似Win32 API——QueryPerformanceFrequency、QueryPerformanceCounter——那样的函数来实现高精度计时
|
|
| 第8楼 zyl910 | 发表于 2006-06-09 09:14 |
| 中级用户 发帖 126 积分 282 | |
|
菜菜的问一下:
TSC、ACPI是什么东西? 怎么利用它们来计时? ACPI貌似是那个高级电源管理,它也有计时功能?昏,现在硬件接口资料真的好难找
|
|
| 第9楼 asbai | 发表于 2006-06-09 13:05 |
| 高级用户 发帖 252 积分 653 | |
|
TSC是奔腾及以上处理器新增的一个64bit的register,在每个CPU基础时钟,该计数器会自动增一(基础时钟是指:流水的stage)。TSC可以使用RDTSC指令读取。
Win32API 中的 QueryPerformanceCounter 确实应该是使用了 TSC,一是它的精度很高,二是MSDN也说了这个API使用了某些硬件相关的特性,在一些CPU上可能不支持。 TSC主要的设计用意是 profiling,在大多数情况下,用它做计时是不合适的,主要是开销较高。 大多数情况下,8253本身最高可以工作在纳秒级的精度上。这个精度对于绝大部分应用来说应该是足够了,但是包括Windows在内的任何操作系统通常不可能让自己的工作粒度保持在这个频率,这会使操作系统本身的维护性开销过大。 再加上Windows处理中断的时候,为了进一步降低开销,还专门使用了DPC机制,所以NT系列的Windows客户端产品的Timer粒度一般在10ms~15ms,服务器产品的粒度一般在15ms~30ms。 通过Windows Native API(不是Win32 API):NtSetTimerResolution,可以改变系统的工作粒度。不过,这个改变会影响当前系统的所有进程,而且不恰当的设置可能会增加系统的管理负担。 更为不爽的是,有迹向表明这个设置很可能也影响系统内核的工作状态,例如:线程调度、阻塞事件和异步IO状态查询等等,调整这个值也相应的增加了这些工作的频率,导致系统性能进一步下滑。 |
|
| 第10楼 asbai | 发表于 2006-06-09 13:14 |
| 高级用户 发帖 252 积分 653 | |
|
ACPI?
zyl910兄是想说Advanced Programmable Interrupt Controller (APIC) Timer? 至于一般说的ACPI Timer,就是RTC在ACPI兼容的系统中引发的周期性计时中断。 Microsoft的硬件开发中心有一篇专门介绍各种硬件Timer和计时问题的文章: http://www.microsoft.com/whdc/system/CEC/mm-timer.mspx |
|
| 第11楼 zyl910 | 发表于 2006-06-10 12:56 |
| 中级用户 发帖 126 积分 282 | |
|
昏
原来TSC是指RDTSC 平时没注意其缩写 非常感谢asbai兄 现在硬件接口编程资料真的好难找 想在DOS下编写一个精确点的计时函数都好麻烦 |
|
| 第12楼 asbai | 发表于 2006-06-10 14:16 |
| 高级用户 发帖 252 积分 653 | |
Originally posted by zyl910 at 2006-6-10 12:56: zyl910兄太客气了,现在硬件资料确实不好找,Intel和AMD发布的x86开发者手册既权威又详细(特别是AMD的),应该是首选资料来源。其它的还有一个网站:http://www.powernet.co.za/info/index.htm,速度虽然慢点,但是资料蛮全的。 俺就知道这么多了,各位兄台有什么好去处,拿出来share一下。 ![]() |
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |