本论坛为只读模式,仅供查阅,不能注册新用户,不能发帖/回帖,有问题可发邮件 xikug.xp (^) gmail.com
查看: 3915|回复: 10

《送别》直接IO版 [复制链接]

Rank: 2

发表于 2009-5-23 19:02:02 |显示全部楼层
很早以前就想写个这样的东西,不过自己是音痴,不会读乐谱.

上次在看雪上看到 玩命大牛写的用BEEP做的《送别》之后,摘抄了曲子,自己实现了直接IO版本.

有几个小细节需要解释:
驱动喇叭的端口:0x61,0x40-0x43.

0x40-0x42是3个计数器,0x40控制系统时钟,0x41控制DRAM刷新的,0x42就是留给一般应用,比如扬声器,我们要用到的就是0x42.

0x43是这3个计数器的控制端口,下面详细解释.

这些端口都是8位操作的,所以每次读写只能操作8位数据.

我在程序中给0x43 OUT 的是0xB6,即10110100.
第0位是0,表示写入的是二进制数,
第1-3位代表计数器的运行方式,010代表以方式2运行,即分频器方式.
第4-5位代表给0x40-0x42端口读写数据的方式,11代表先读低8位,再读高8位.
第6-7位代表选择的计数器,10代表选择选择计数器2,即0x42端口.

再来解释0x61端口.
计数器2的时钟信号一个1193180Hz的输入,计数器2的另外一个输入是0x61端口的第0位,当第0位为1时,计数器2启动.
另外,计数器2的输出端和0x61端口的第1位经过与门之后输出到喇叭,以此来驱动喇叭.

所以要让喇叭启动,就把0x61端口的低两位置1就可以了,要停止就置0.

详细的看代码.

解释完了,希望不是废话.

下面看代码.
  1. #define ONE_MyBeep 600
  2. #define HALF_MyBeep 300
  3. #define NOTE_1 440
  4. #define NOTE_2 495
  5. #define NOTE_3 550
  6. #define NOTE_4 587
  7. #define NOTE_5 660
  8. #define NOTE_6 733
  9. #define NOTE_7 825
  10. UCHAR In_8(PUCHAR Port)
  11. {
  12. UCHAR Value;
  13. __asm
  14. {
  15. mov edx,Port
  16. in al,dx
  17. mov Value,al
  18. nop
  19. nop
  20. }
  21. return Value;
  22. }
  23. void Out_8(PUCHAR Port,UCHAR Value)
  24. {
  25. __asm
  26. {
  27. mov edx,Port
  28. mov al,Value
  29. out dx,al
  30. nop
  31. nop
  32. }
  33. }
  34. void MyBeep(USHORT freq,ULONG duration)
  35. {
  36. LARGE_INTEGER timeout;
  37. UCHAR stop;
  38. USHORT timer=1193180/freq;
  39. UCHAR start;
  40. start=In_8((PUCHAR)0x61);
  41. start=start|3;
  42. timeout=RtlConvertLongToLargeInteger(-10000*duration);
  43. /*0x61端口低两位置1,启动喇叭*/
  44. Out_8((PUCHAR)0x61,start);
  45. /*计数器控制端口0x43,置位为10110100*/
  46. Out_8((PUCHAR)0x43,0xB4);
  47. /*先写低八位*/
  48. Out_8((PUCHAR)0x42,timer&0xF);
  49. /*再写高八位*/
  50. Out_8((PUCHAR)0x42,(timer>>8)&0xF);
  51. /*喇叭持续时间*/
  52. KeDelayExecutionThread(KernelMode,FALSE,&timeout);
  53. /*0x61端口低两位置0,停止喇叭*/
  54. stop=In_8((PUCHAR)0x61);
  55. stop=stop&0xFC;
  56. Out_8((PUCHAR)0x61,stop);
  57. }
  58. void PlayMusic(void)
  59. {
  60. MyBeep(NOTE_5, ONE_MyBeep);
  61. MyBeep(NOTE_3, HALF_MyBeep);
  62. MyBeep(NOTE_5, HALF_MyBeep);
  63. MyBeep(NOTE_1*2, ONE_MyBeep*2);
  64. MyBeep(NOTE_6, ONE_MyBeep);
  65. MyBeep(NOTE_1*2, ONE_MyBeep);
  66. MyBeep(NOTE_5, ONE_MyBeep*2);
  67. MyBeep(NOTE_5, ONE_MyBeep);
  68. MyBeep(NOTE_1, HALF_MyBeep);
  69. MyBeep(NOTE_2, HALF_MyBeep);
  70. MyBeep(NOTE_3, ONE_MyBeep);
  71. MyBeep(NOTE_2, HALF_MyBeep);
  72. MyBeep(NOTE_1, HALF_MyBeep);
  73. MyBeep(NOTE_2, ONE_MyBeep*4);
  74. MyBeep(NOTE_5, ONE_MyBeep);
  75. MyBeep(NOTE_3, HALF_MyBeep);
  76. MyBeep(NOTE_5, HALF_MyBeep);
  77. MyBeep(NOTE_1*2, HALF_MyBeep*3);
  78. MyBeep(NOTE_7, HALF_MyBeep);
  79. MyBeep(NOTE_6, ONE_MyBeep);
  80. MyBeep(NOTE_1*2, ONE_MyBeep);
  81. MyBeep(NOTE_5, ONE_MyBeep*2);
  82. MyBeep(NOTE_5, ONE_MyBeep);
  83. MyBeep(NOTE_2, HALF_MyBeep);
  84. MyBeep(NOTE_3, HALF_MyBeep);
  85. MyBeep(NOTE_4, HALF_MyBeep*3);
  86. MyBeep(NOTE_7/2, HALF_MyBeep);
  87. MyBeep(NOTE_1, ONE_MyBeep*4);
  88. MyBeep(NOTE_6, ONE_MyBeep);
  89. MyBeep(NOTE_1*2, ONE_MyBeep);
  90. MyBeep(NOTE_1*2, ONE_MyBeep*2);
  91. MyBeep(NOTE_7, ONE_MyBeep);
  92. MyBeep(NOTE_6, HALF_MyBeep);
  93. MyBeep(NOTE_7, HALF_MyBeep);
  94. MyBeep(NOTE_1*2, ONE_MyBeep*2);
  95. MyBeep(NOTE_6, HALF_MyBeep);
  96. MyBeep(NOTE_7, HALF_MyBeep);
  97. MyBeep(NOTE_1*2, HALF_MyBeep);
  98. MyBeep(NOTE_6, HALF_MyBeep);
  99. MyBeep(NOTE_6, HALF_MyBeep);
  100. MyBeep(NOTE_5, HALF_MyBeep);
  101. MyBeep(NOTE_3, HALF_MyBeep);
  102. MyBeep(NOTE_1, HALF_MyBeep);
  103. MyBeep(NOTE_2, ONE_MyBeep*4);
  104. MyBeep(NOTE_5, ONE_MyBeep);
  105. MyBeep(NOTE_3, HALF_MyBeep);
  106. MyBeep(NOTE_5, HALF_MyBeep);
  107. MyBeep(NOTE_1*2, HALF_MyBeep*3);
  108. MyBeep(NOTE_7, HALF_MyBeep);
  109. MyBeep(NOTE_6, ONE_MyBeep);
  110. MyBeep(NOTE_1*2, ONE_MyBeep);
  111. MyBeep(NOTE_5, ONE_MyBeep*2);
  112. MyBeep(NOTE_5, ONE_MyBeep);
  113. MyBeep(NOTE_2, HALF_MyBeep);
  114. MyBeep(NOTE_3, HALF_MyBeep);
  115. MyBeep(NOTE_4, HALF_MyBeep*3);
  116. MyBeep(NOTE_7/2, HALF_MyBeep);
  117. MyBeep(NOTE_1, ONE_MyBeep*3);
  118. }
复制代码

PlayMusic.rar

3 KB, 下载次数: 648

Rank: 4

发表于 2009-5-23 21:22:21 |显示全部楼层
虽然不好听,不过还是支持下.

Rank: 2

发表于 2009-5-24 00:50:41 |显示全部楼层
我是个音痴

懂音乐的可以改下频率和节拍,应该会好听点

Rank: 4

发表于 2009-5-24 01:29:55 |显示全部楼层
音痴,乐盲飘过~

Rank: 1

发表于 2010-3-17 13:19:59 |显示全部楼层
同样 ..音肓...

Rank: 3Rank: 3

发表于 2010-3-17 13:33:37 |显示全部楼层
引用第4楼wslijs1988于2010-03-17 10:19发表的  :
同样 ..音肓...
++

Rank: 1

发表于 2010-3-17 13:58:01 |显示全部楼层
引用第3楼achillis于2009-05-23 22:29发表的  :
音痴,乐盲飘过~

Rank: 1

发表于 2010-3-19 18:59:27 |显示全部楼层
下載來聽聽

Rank: 1

发表于 2010-3-22 17:33:26 |显示全部楼层
呵呵,回到dos下编程的感觉。

Rank: 1

发表于 2010-3-23 15:56:20 |显示全部楼层
音准不对,希望再增加其他音高。就完美了

Rank: 1

发表于 2010-3-23 16:17:12 |显示全部楼层
{131,147,165,175,196,220,247},
    {262,294,330,349,392,440,494},
    {523,587,659,698,784,880,988},
    {1047,1174,1319,1568,1760,1976}};
感觉这组频率 对应的音准不对
您需要登录后才可以回帖 登录 | 立即加入

Archiver|手机版|第8个男人 - 论坛为只读模式,仅供查阅

GMT+8, 2019-6-27 07:14 , Processed in 0.025229 second(s), 11 queries .

Design by pvo.cn

© 2011 Pvo Inc.

回顶部