《单片机电子琴的设计 (最新).docx》由会员分享,可在线阅读,更多相关《单片机电子琴的设计 (最新).docx(27页珍藏版)》请在三一办公上搜索。
1、目 录前 言1第一章 设计要求及工作原理21.1 基本设计要求21.2 方案比较与确定21.3 系统组成与工作原理2第二章 硬件电路设计62.1 单片机最小系统62.2 键盘模块92.3 方波发生模块122.4 功率放大发声模块13第三章 软件设计143.1 软件结构功能设计143.2 主程序设计143.3 子程序设计15第四章 实验调试及测试结果分析174.1 软件调试174.2系统联调18结论19参考文献20附录1:系统原理图21附录2 源程序22附录3 电子琴成品图26附录4元件清单27前 言又称作电子键盘,属于电子乐器(区别于电声乐器),发音音量可以自由调节。音域较宽,和声丰富,甚至可
2、以演奏出一个管弦乐队的效果,表现力极其丰富。它还可模仿多种音色,甚至可以奏出常规乐器所无法发出的声音(如合唱声,风雨声,宇宙声等)。另外,电子琴在独奏时,还可随意配上类似打击乐音响的节拍伴奏,适合于演奏节奏性较强的现代音乐。另外,电子琴还安装有效果器,如混响、回声、延音,震音轮和调制轮等多项功能装置,表达各种情绪时运用自如。 电子琴是电声乐队的中坚力量,常用于独奏主旋律并伴以丰富的和声。还常作为独奏乐器出现,具有鲜明时代特色。但电子琴的局限性也十分明显:旋律与和声缺乏音量变化,过于协和、单一;在模仿各类管、弦乐器时,技法略显单调。电子琴是一种功能强大,易于制作,成本低廉的现代新型乐器。它可根据
3、使用者的不同要求方便的进行设计,成为现代社会一种颇具市场号召力的乐器。单片机具有强大的控制功能和灵活的编程实现特性,在现代工业生活中随处可见,本次课程设计主要就是利用STC89C52单片机为核心控制元件,设计简易的一个电子琴,并以此对电子琴原理及硬件组成进行分析并设计,最终由此做出实物。由此更进一步掌握微机原理及应用课程的有关知识,提高应用微机解决问题的能力,加深对微机应用的理解。通过查阅资料,结合所学知识进行软、硬件的设计,初步掌握应用微机解决问题的步骤及方法。为以后结合专业从事微机应用设计奠定基础。第一章 设计要求及工作原理1.1 基本设计要求1 基于单片机STC89C52为核心。2 利用
4、定时/计数器8253设计并制作一个简易电子琴。3 设计至少8个按键,每个按键对应一种音调,即1、2、3、4、5、6、7、8八个不同的音节。4 按下按键发声,松开按键后声音延迟一段时间后停止,可弹奏简单的乐曲。1.2 方案比较与确定 方案一:使用单片机内部定时器,通过编程实现发出不同频率方波,产生音阶。 方案二:使用8253作为外部定时器,通过编程实现产生所需频率的方波。 通过对方案一和方案二的比较可以知道,方案一是通过使用单片机内部定时器,以编程实现方波输出,优点在于外部电路简单,程序结构简单,缺点在于消耗单片机资源过多,不利于优化升级;方案二是利用8253来产生方波,相对来说这种方案外部电路
5、较为复杂,程序结构也更为复杂,优点在于占用单片机资源少,输出稳定,利于扩展;故而选择方案二较好1.3 系统组成与工作原理声音的频谱范围约在几十到几千赫兹, 若能利用程序来控制单片机某个口线不断输出“ 高” “ 低”电平, 则在该口线上就能产生一定频率的方波, 将该方波接上喇叭就能发出一定频率的声音, 若再利用程序控制“ 高” “ 低”电平的持续时间, 就能改变输出波形的频率从而改变音调。乐曲中, 每一音符对应着确定的频率, 下表给出各音符频率。如果单片机某个口线输出“ 高” “ 低”电平的频率和某个音符的频率一样, 那么将此口线接上喇叭就可以发出此音符的声音。本系统就是根据此原理设计, 对于单
6、片机来说要产生一定频率的方波大致是先将某口线输出高电平然后延时一段时间再输出低电平, 如此循环的输出就会产生一定频率的方波, 通过改变延时的时间就可以改变输出方波的频率。单片机内部有两个位的定时计数器T1和T0, 单片机的定时计数器实际上是个计数装置它既可以对单片机的内部晶振驱动时钟计数也可以对外部输入的脉冲计数, 对内部晶振计数时称为定时器, 对外部时钟计数时称为计数器。当对单片机的内部晶振驱动时钟计数时,每个机器周期定时计数器的计数值就加, 当计数值达到计数最大值时计数完毕并通知单片机的尸比对外部输入的时钟信号计数时, 外部时钟的每个时钟上升沿定时计数器的计数值就加, 当计数值达到计数最大
7、值时计数完毕并通知单片机的尸。因此, 如果知道单片机的机器周期或者外部输入时钟信号的周期单片机就可以根据定时器的计数值计算出定时的时间。用此方法定时十分准确, 想得到多大的延时时间就可以给定时器赋一定的计数初值, 定时器从预先设置的计数初值开始不断增当增加到计数最大值时计数完毕, 调整计数初值的大小就可以调整定时器定时的时间, 从而达到准确的延时。在本设计中我们使用的外部时钟信号的晶振频率为12MHz,而采用的计数方式为方式1,所以计数器的初始值可以由如下公式求得。 T=65536-1000000/2/ff为对应音调的频率;输出频率对照表: 0xA9,0xEF,/00220HZ ,1 /0 0
8、x93,0xF0,/00233HZ ,1# 0x73,0xF1,/00247HZ ,2 0x49,0xF2,/00262HZ ,2# 0x07,0xF3,/00277HZ ,3 0xC8,0xF3,/00294HZ ,4 0x73,0xF4,/00311HZ ,4# 0x1E,0xF5,/00330HZ ,5 0xB6,0xF5,/00349HZ ,5# 0x4C,0xF6,/00370HZ ,6 0xD7,0xF6,/00392HZ ,6# 0x5A,0xF7,/00415HZ ,7 0xD8,0xF7,/00440HZ 1 /12 0x4D,0xF8,/00466HZ 1# /13 0xB
9、D,0xF8,/00494HZ 2 /14 0x24,0xF9,/00523HZ 2# /15 0x87,0xF9,/00554HZ 3 /16 0xE4,0xF9,/00587HZ 4 /17 0x3D,0xFA,/00622HZ 4# /18 0x90,0xFA,/00659HZ 5 /19 0xDE,0xFA,/00698HZ 5# /20 0x29,0xFB,/00740HZ 6 /21 0x6F,0xFB,/00784HZ 6# /22 0xB1,0xFB,/00831HZ 7 /23 0xEF,0xFB,/00880HZ 1 0x2A,0xFC,/00932HZ 1# 0x62,0
10、xFC,/00988HZ 2 0x95,0xFC,/01046HZ 2# 0xC7,0xFC,/01109HZ 3 0xF6,0xFC,/01175HZ 4 0x22,0xFD,/01244HZ 4# 0x4B,0xFD,/01318HZ 5 0x73,0xFD,/01397HZ 5# 0x98,0xFD,/01480HZ 6 0xBB,0xFD,/01568HZ 6# 0xDC,0xFD,/01661HZ 7 /35 基于STC89S52单片机,以8253作为外部中断,通过7279进行键盘控制,设计一个电子琴。单片机作为主控核心,通过对7279的键盘按键键值进行定义,让定时器8253产生8个
11、特定频率的方波,通过由LM386组成外部功放电路输出至扬声器发出123456718个不音阶。硬件部分主要功能模块包含:键盘控制模块、方波发生模块、声音输出模块。八个音节do、re、mi、fa、sol、la、si、do所对应的频率分别为523HZ、587HZ、659HZ、698HZ、784HZ、880HZ、988HZ、1047HZ。软件部分主要功能模块包含:主程序、8253方波发生子程序、7279初始化子程序、接收发送字节子程序、延时子程序等当按下特定的按键后,程序通过读键值子程序得到所按下键的键值,再将所得的键值与键盘1、2、3、4、5、6、7、8八个键的键值相比较,从而确定所按下的键。当确认
12、按键后再调用8253方波发生子程序,使8253产生相应频率的方波持续输出。系统原理框图如图1.1所示:7279键盘模块单片机AT89C51定时/计数器8253功率放大电路喇叭发声模块图1.1 系统原理框图第二章 硬件电路设计2.1 单片机最小系统 STC89C52主要特性: 与MCS-51 兼容8K字节可编程闪烁存储器寿命:1000写/擦循环数据保留时间:10年全静态工作:0Hz-24Hz三级程序存储器锁定512内部RAM32可编程I/O线两个16位定时器/计数器5个中断源可编程串行通道低功耗的闲置和掉电模式片内振荡器和时钟电路管脚说明: VCC:供电电压。 GND:接地。 P0口:P0口为一
13、个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。 P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。 P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可
14、接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。 P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,
15、P3口将输出电流(ILL)这是由于上拉的缘故。 P3口也可作为AT89C51的一些特殊功能口,如下表所示: 口管脚 备选功能 P3.0 RXD(串行输入口) P3.1 TXD(串行输出口) P3.2 /INT0(外部中断0) P3.3 /INT1(外部中断1) P3.4 T0(记时器0外部输入) P3.5 T1(记时器1外部输入) P3.6 /WR(外部数据存储器写选通) P3.7 /RD(外部数据存储器读选通) P3口同时为闪烁编程和编程校验接收一些控制信号。 RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。 ALE/PROG:当访问外部存储器时,地址锁存允许的
16、输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。 /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将
17、不出现。 /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。 XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。 XTAL2:来自反向振荡器的输出。 振荡器特性: XTAL1和XTAL2分别为反向放大器的输入和输出。该反向放大器可以配置为片内振荡器。石晶振荡和陶瓷振荡均可采用。如采用外部时钟源驱动器件,XTAL2应不接。有余输入至内部时钟信号要通过一个二分频触发器,因
18、此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。图2-1 STC89C52结构图单片机最小系统主要由时钟电路和复位电路组成。此系统的时钟电路设计是采用的内部方式,即利用芯片内部的振荡电路。MCS-51内部有一个用于构成振荡器的高增益反相放大器。引脚XTAL1和XTAL2分别是此放大器的输入端和输出端。这个放大器与作为反馈元件的片外晶体谐振器一起构成一个自激振荡器。外接晶体谐振器以及电容CX1和CX2构成并联谐振电路,接在放大器的反馈回路中。,此系统电路的晶体振荡器的值为12MHz,电容值约为30F。 图2.2 时钟电路复位电路是由外部的复位电路来实现的。片内复位电路是复位
19、引脚RST通过一个斯密特触发器与复位电路相连,斯密特触发器用来抑制噪声,它的输出在每个机器周期的S5P2,由复位电路采样一次。其原理图如图3.1所示图2.3 单片机最小系统原理图2.2 键盘模块HD7279是一片具串行接口的,可同时驱动8位共阴式数码管(或64只独立LED)的智能显示驱动芯片,该芯片同时还可以连接多达64键的键盘矩阵,单片即可完成LED显示、键盘接口的全部功能。HD7279内不含有译码器,可直接接收BCD码或16进制码,并同时具有2种译码方式,此外i,还具有多种控制指令,如消隐、闪烁、左移、右移、段寻址等。HD7279具有片选信号,可方便地实现多于8位的显示或多于64键的键盘接
20、口。1 主要特性:(1) 串行接口,无需外围元件可直接驱动LED。(2) 各位独立控制译码/不译码及消隐和闪烁属性。(3) (循环)左移/(循环)右移指令(4) 具有段寻址指令,方便控制独立LED(5) 64键键盘控制器,内含去抖动电路(6) 有DIP和SOIC两种封装形式供选择2 引脚说明: 图2-4 7279引脚说明图2-5 7279管脚图键盘模块主要由键盘串行接口芯片7279扩展组成。键盘采用4*4矩阵式,按键检查使用行列扫描方式,行设置低电平,同时读入列状态,如果列状态不是全为1,则此列与行为0相交的键就是所按下的键。在应用过程中,只需要将7279的CS、CLK、DATA和KEY四个端
21、口分别连接至单片机的P1.0、P1.1、P1.2和P1.3即可。当全部硬件电路连接好后,按下键盘的按键,单片机将获得该按键的键值,通过软件编程即可确定所需要的方波频率值,使8253产生该频率的方波,经由功放电路输出至喇叭发声。其原理图如图2-6所示: 图2.6 7279键盘模块原理图2.3 方波发生模块方波发生模块主要由STC89C52、74LS373、74LS138和8253组成。其中,74LS138的A、B、C口分别连接至AT89C51的P2.5、P2.6和P2.7,E1、E2、E3分别连接至P2.2、P2.3和P2.4口,由译码器74LS138的Y5口输出。由硬件连接可确定端口地址为:0
22、A000H、0A001H、0A002H和0A003H。锁存器74LS373的D0和D1口分别连接至P0.0和P0.1,Q0和Q1口分别连接至8253的A0和A1口,用于地址锁存。8253的D0到D7口分别连接至STC89C52的P0.0至P0.7口,GATE0口持续接高电平,CLK2处的时钟信号经由分频电路连接至单片机的读和写,使8253有稳定的2MHZ的时钟信号输入,最后在OUT2口便可产生持续的方波输出,频率则由软件编程决定。其原理图如图2.6所示:图2.7 方波发生模块原理图2.4 功率放大发声模块 功放模块主要由扬声器和LM386构成,OUT2信号输出至LM386信号输入端,经由放大电
23、路放大后输出至扬声器发声。其原理图如图2.7所示:图2.8 喇叭发声模块原理图第三章 软件设计3.1 软件结构功能设计软件部分主要包含:主程序、8253方波发生子程序、7279初始化子程序、接收发送字节子程序、延时子程序等。主程序:判断所读取的键值,并根据键值赋值do、re、mi、fa、sol、la、si、do八个音节的频率。运用switch语句,让所选用的8个键值分别与8个音阶的频率所对应。8253方波发生子程序:设定好8253的控制字,且为方式3工作方式(方波发生器)。将8个音节的8个不同频率转换成16进制数后赋值给8253的输出端口地址后相减,即可。7279初始化子程序:使片选信号的上升
24、沿时刻复位,使芯片处于上电复位状态。接收发送字节子程序:通过移位将所需要传送的字节存于A中,以便于其它程序进行调用延时子程序:通过for循环得到延时子程序。3.2 主程序设计主程序先对7279进行初始化,调用键值读取子程序,对读取的键值进行判断是否为预设的键值,若不是则返回,若是怎进入switch语句进行赋值。其主程序流程框图如图3.1所示:保存键值调用方波发生子程序开始调用读键值子程序是数字18键吗?程序初始化NYNY图3.1 主程序流程框图3.3 子程序设计方波发生子程序:对8253进行初始化,控制字赋值,确定工作在方式3,初值送至入口地址。其子程序流程框图如图3.2所示:判断是否有键按下
25、,若有,则发送读键盘数据指令,并保存键值。其子程序流程框图如图3.3所示:方波发生子程序入口8253控制字赋值设置入口地址赋初值读键值子程序入口是否有键按下?发送读键盘数据指令YN将键值保存于A中子程序返回子程序返回图3.2 方波发生子程序流程框图图3.3 读键值子程序流程框图7279初始化子程序:发送复位指令,子程序返回。其子程序流程框图如图3.4所示:发送一字节子程序:将所需发送的字节带进位左移一位,循环八次后将所需发送的字符保存于A中,子程序返回。其子程序流程框图如图3.5所示:初始化子程序入口发送复位指令发送一字节子程序入口发送复位指令是否循环8次?发送字符存于A中YN子程序返回图3.
26、4 7279初始化子程序流程框图 图3.5 发送一字节子程序流程框图第四章 实验调试及测试结果分析4.1 软件调试本次课程设计简易电子琴的软件设计我并没有运用汇编语言,而是运用了并没有在课程中学习的C语言,故在设计的时候遇到较大的困难。主要是对于初始化方面不熟悉,后通过上网学习及日立电子钟的设计对单片机的C程序设计运用较为熟练。首先对于一些需要使用的数据类型进行定义,如#define uint unsigned int;后用XBYTE命令对8253进行初始化,用sbit指令对7279进行初始化。然后编写各子程序,最后编写主程序。开始时用的是if(!key=*)语句来进行键值的判断,后进行单独赋
27、值的办法,但是后来发现这样的语句对于只有几个音阶的简易电子琴来说还具有可行性,但是对于音阶较多的就显得太为繁杂了,故后建立数组,编写了频率对照表,运用switch语句进行键值判断并查表赋值。这样的设计使得此程序的可扩展性较强。运用TR0来控制发声。当硬件连接好后,我们把程序烧录进单片机进行初步调试,发现没有任何反应,排查后排除了硬件问题,然后进行了软件排查。1单独编写了方波发生程序,发现能发出方波,但是幅度及频率均与理论值相差巨大。2由于硬件排查时认为单片机及功放两部分工作正常,为了验证这个结论的正确性,我们先在硬件电路上绕过8253,单片机输出直接连接功放模块,然后改写程序,使用单片机内部中
28、断,发现一切工作正常,且可在7279键盘上弹奏音乐。此结果直接证明之前问题出在8253的论断完全正确,也间接证明程序的编写基本没有问题。3后为了证明程序编写的正确性,我们把自己程序里的一些初始化数值进行了更改,达到与别组硬件匹配后,把自己的程序烧录进别组的硬件中,发现可以工作。最后由于时间问题,我们没有排查出8253的问题,于是更改了之前的设计,去掉了8253运用方案一进行设计。在方案一的调试中遇到以下几个问题:1. 发声频率有误差:运用示波器观察,对根据公式更改参数达到要求。2. 按键与设定音阶不符:检查程序为switch语句case设置偏差。经调试后,程序运行正确,达到设计要求。后期课程设
29、计结束后自己增加了锁定功能,自动播放功能。4.2系统联调经硬件检测,程序调试后,将程序下载到单片机,按下所设置的键,与设计要求相比对,扬声器可正常发出中音8音阶,运用示波器检查,8音阶频率稍有误差,基本与理论值相同,达到要求,结果在误差范围之内。根据乐谱弹奏,可弹奏出正常乐曲。后期,对程序进行了升级,加入了节奏控制(以按键时间长短来控制延时长短),建立了乐曲频率数组,可播放数组中所存乐曲。此次简易电子琴设计完成。结论总的来说,本次的简易电子琴设计不是很成功,因为时间关系,最终没能找出预先设计中的问题,最后只能通过更改设计来实现目的。但是也收获颇多;首先我主要负责软件的编写,使我对单片机的C程序
30、设计从无到有,从不会到会,深入的了解了单片机程序设计中汇编与C两种语言的优劣点,使我以后设计程序时对语言的选择有了一个清醒的认识。进而发现问题就要解决问题,在这次解决问题中发现了自己很多不懂得知识,为了解决问题自己去找资料学习,并且在老师的指导下学会了如何有条理的去排查问题以及如何去验证自己的猜测。特别是在我所主要负责的程序方面,在一次次的验证中不断编写各种功能的程序,从刚开始的什么都不懂,经常要自己上网找资料学习,都后来在编写程序中总能有各种奇思妙想,经常能有一些让自己都经不住感叹的构思,对C语言有一种得心应手的感觉。自己在这之中编写了很多各种功能的程序,如对电子琴进行锁定,录制等功能。最后
31、,虽说这次的课程设计结果不是很成功,但是过程中的收获却是相当多的。参考文献 1 杨学昭.单片机原理、接口技术及应用(含c51),2009年2月2 佚名.娱乐应用电路集粹. 机械工业出版社,2005年2月3 阎石.数字电子技术基础.北京:高等教育出版社,2006年5月4 何宏、龚威.单片机原理与接口技术.北京:国防工业出版社,20065 楼然苗、李光飞 .单片机课程设计指导.北京:北京航空航天大学出版社,20076 王福瑞等 .单片机测控系统设计大全.北京:北京航空航天大学出版社,19997 张友德、赵志英、涂时亮.单片机微型机原理、应用与实验.上海:复旦大学出版社,2006第五版8 徐新艳.单
32、片机原理、应用与实践.北京:高等教育出版社,2005年3月9 张毅刚.MCS-51单片机应用设计.哈尔滨:哈尔滨工业大学出版社,200410 杨兴瑶.实用电子电路500例.化学工业出版社,1996附录1:系统原理图附录2 源程序#include /包括一个 52 标准内核的头文件 #include /XBYTE头文件 #define COM8253 XBYTE 0x0A003#define COM8253_H XBYTE 0x0A0#define COM8253_L XBYTE 0x002#define uchar unsigned char /定义一下方便使用 #define uint un
33、signed int #define ulong unsigned long #define uchar unsigned char#define uint unsigned intunsigned char key_number;unsigned char flag;#define CMD_RESET 0xa4 /restart#define DECODE1 0xc8/downlaod 1 #define CMD_READ 0x15/ read key#define BLINKCTL 0x88 / blink /*HD7279连接*sbit cs=P10; / cs P1.0sbit clk
34、=P11; / clk P1.1sbit dat=P12; / data P1.2sbit key=P13; / key P1.3/长短延时程序void long_delay(void) unsigned char i; for (i=0;i0x30;i+);void short_delay(void) unsigned char i; for (i=0;i8;i+);void send_byte( unsigned char out_byte) /发送字节到7279 unsigned char i; cs=0; long_delay(); for (i=0;i8;i+) if(out_byt
35、e&0x80) dat=1; else dat=0; clk=1; short_delay(); clk=0; short_delay(); out_byte=out_byte*2; dat=0;/7279接收发送子程序unsigned char receive_byte(void) /接收7279一个字节 unsigned char i, in_byte; dat=1; long_delay(); for (i=0;i8;i+) clk=1; short_delay(); in_byte=in_byte*2; if (dat) in_byte=in_byte|0x01; clk=0; sho
36、rt_delay(); dat=0; return (in_byte);void write7279(unsigned char cmd, unsigned char dta) send_byte (cmd); send_byte (dta);unsigned char read7279(unsigned char command) send_byte(command); return(receive_byte();/* 键值表 : 31 30 29 28 23 22 21 20 15 14 13 12 7 6 5 4*/输出频率对照表 uchar code freq36*2= 0xA9,0x
37、EF,/00220HZ ,1 /0 0x93,0xF0,/00233HZ ,1# 0x73,0xF1,/00247HZ ,2 0x49,0xF2,/00262HZ ,2# 0x07,0xF3,/00277HZ ,3 0xC8,0xF3,/00294HZ ,4 0x73,0xF4,/00311HZ ,4# 0x1E,0xF5,/00330HZ ,5 0xB6,0xF5,/00349HZ ,5# 0x4C,0xF6,/00370HZ ,6 0xD7,0xF6,/00392HZ ,6# 0x5A,0xF7,/00415HZ ,7 0xD8,0xF7,/00440HZ 1 /12 0x4D,0xF8,
38、/00466HZ 1# /13 0xBD,0xF8,/00494HZ 2 /14 0x24,0xF9,/00523HZ 2# /15 0x87,0xF9,/00554HZ 3 /16 0xE4,0xF9,/00587HZ 4 /17 0x3D,0xFA,/00622HZ 4# /18 0x90,0xFA,/00659HZ 5 /19 0xDE,0xFA,/00698HZ 5# /20 0x29,0xFB,/00740HZ 6 /21 0x6F,0xFB,/00784HZ 6# /22 0xB1,0xFB,/00831HZ 7 /23 0xEF,0xFB,/00880HZ 1 0x2A,0xFC
39、,/00932HZ 1# 0x62,0xFC,/00988HZ 2 0x95,0xFC,/01046HZ 2# 0xC7,0xFC,/01109HZ 3 0xF6,0xFC,/01175HZ 4 0x22,0xFD,/01244HZ 4# 0x4B,0xFD,/01318HZ 5 0x73,0xFD,/01397HZ 5# 0x98,0xFD,/01480HZ 6 0xBB,0xFD,/01568HZ 6# 0xDC,0xFD,/01661HZ 7 /35 ; uchar code jie88=12,14,16,17,19,21,23,24;/12345671 八个音符在频率表中的位置 /定时
40、中断 0,用于产生唱歌频率 /timer0() interrupt 1 /按键控制音阶声音输出(电子琴) /主函数void main()COM8253=0xB6; send_byte(CMD_RESET); while (1) if (!key) short_delay(); if(!key) key_number=read7279(CMD_READ); switch(key_number) case 4: COM8253_H= freqjie80*2; COM8253_L=freqjie80*2+1;break;case 5: COM8253_H= freqjie81*2; COM8253_
41、L=freqjie81*2+1;break;case 6: COM8253_H= freqjie82*2; COM8253_L=freqjie82*2+1;break;case 7: COM8253_H= freqjie83*2; COM8253_L=freqjie83*2+1;break; case 12: COM8253_H= freqjie84*2; COM8253_L=freqjie84*2+1; break;case 13: COM8253_H= freqjie85*2; COM8253_L=freqjie85*2+1; break;case 14: COM8253_H= freqjie86*2; COM8253_L=freqjie86*2+1; break;case 15: COM8253_H= freqjie87*2; COM8253_L=freqjie87*2+1;