音乐发生器实验
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
音乐发生器实验
目录
1 前言 (2)
2 需求分析 (2)
2.1原理 (2)
2.2要求 (2)
2.3任务 (2)
2.4运行环境 (2)
2.5开发工具 (2)
3 概要设计 (3)
3.1系统流程图: (3)
3.2音符文件读取程序流程图 (3)
3.3播放子程序 (4)
3.4延时子程序 (4)
4 详细设计 (5)
4.1歌曲编排 (5)
4.2分析和设计 (5)
4.3具体代码实现 (8)
5 课程设计的总结与体会 (13)
6 致谢 (13)
7 参考资料 (13)
1前言
编写一个程序来初始化8253定时/计数器和8255并行通信接口芯片。通过接口控制音乐发声器的播放和灯光的闪烁,实现通过运行在MFDI平台运行程序对硬件电路的控制。
2需求分析
2.1 原理
编写程序对8253和8255芯片进行初始化,按照音符来设定频率和8253定时/计数器的延时时间。对8255芯片pc0和pc6口的置0和1来控制扬声器的开关,对pc4口的置0和1控制LED灯的闪烁。
2.2 要求
(1)熟悉电路,理解各个元件之间的控制流程。
(2)熟悉MFDI平台的运行环境。
(3)熟练掌握C语言,调用中断子程序和端口函数对端口进行读写数据的操作。
(4)理解乐谱知识,熟悉音频转换表和节拍的延长时间
2.3 任务
(1)曲谱转换
(2)分析电路图
(3)画出程序流程图
(4)编写代码
(5)程序分析与调试
(6)测试
2.4 运行环境
(1)WINDOWS2000/XP系统
(2)MFDI实验平台
(3)VC编译环境
2.5 开发工具
C语言
3概要设计
3.1 系统流程图(如图3.1):
图3.1 系统流程图3.2 音符文件读取程序流程图(如图3.2):
图3.2 音符文件读取流程图3.3 播放子程序流程图(如图3.3):
图3.3 播放流程图3.4 延时子程序流程图(如图3.4):
图3.4 延时流程图
4详细设计
4.1 歌曲编排
根据歌曲的音符来获取它的频率和延时时间,具体介绍请参考《音乐发声器-音
乐篇》
4.2 分析和设计
在程序的开头部分是声明了四首歌曲的频率和延时时间然后分别定义了指向频
率数组和延时数组的指针,
void interrupt (*oldhandler)(__CPPARGS);
void interrupt handler(__CPPARGS)
{
(*pTimeDelay) -- ; // 延时点数减一
oldhandler(); // 调用原例程}
这个函数表示的是调用的延时子程序。然后声明了4个Playing函数,来调用4首歌的播放子程序。下面是编写的4个read函数,分别是从文件里读出4首歌的音符。通过转换表转换成16进制的数字(如表4.1)。
表4.1 音符——灯光闪烁频率表
说明当音符为‘1’时,相应的闪烁一个灯为0x1,音符为‘2’时,相应的闪烁
两个灯为0x3,依次规律类推。
int * read(char *p)
{ int i;
FILE * fp;
int aa[300],* pp;
fp=fopen(p,"r");
while((aa[i]= fgetc(fp))!=-1)
{ switch(aa[i])
{ case '1':bb[i]=0x1;break;
case '2':bb[i]=0x3;break;
case '3':bb[i]=0x7;break;
case '4':bb[i]=0xf;break;
case '5':bb[i]=0x1f;break;
case '6':bb[i]=0x3f;break;
case '7':bb[i]=0x7f;break;}
i++;}
pp = dd;
return pp;
}
这个程序主要是从文件中读取音符,然后把读到的音符通过音符——灯光闪烁
频率表转化成相应的16进制。读完了后放到一个数组中,然后返回一个数组指针。
int Playing(void)
{
oldhandler = getvect(INTR); // 保存原中断向量
setvect(INTR, handler); // 装载新中断向量
outportb( 0x303, 0x90); // 初始化8255
outportb( 0x303, 0x0c); // 置pc6=0 禁止8253通道2的gate引脚
outportb( 0x303, 0x00); // 置pc0=0 禁止7408
outportb( 0x307, 0xb6); // 初始化8253
pFreq = pf; // 取歌曲的第一个音频
pTimeDelay = pt; // 取歌曲的第一个时延
while ( *pFreq && !kbhit())
{
outportb( 0x306, (unsigned char)(CLK / *pFreq % 256));
// 先送低字节
outportb( 0x306, (unsigned char)(CLK / *pFreq / 256));
// 再送高字节
// 以上置8253通道2 的计数初值
outportb( 0x303, 0x01);
outportb( 0x303, 0x0d); // 开扬声器
*pr = ~*pr;
outportb(0x301,*pr);