《51单片机应用开发从入门到精通》——2.11 歌曲演奏实例

2.11 歌曲演奏实例

本实例是利用单片机演奏一首生日快乐歌。

2.11.1 编程演奏器原理

1.演奏器原理

(1)通过控制单片机定时器的定时时间产生不同频率的音频脉冲,经放大后驱动蜂鸣器发出不同音节的声音。

(2)用软件延时来控制发音时间的长短,控制节拍,表2-14是各调1/4节拍的时间表。

(3)把乐谱中的音符和相应的节拍变换为定时常数和延时常数,作为数据表格存放在存储器中。由程序查表得到定时常数和延时常数,分别用来控制定时器产生的脉冲频率和发出该音频脉冲的持续时间。

(4)表2-15为单片机晶振频率为12MHz时,乐曲中的音符、频率及定时常数之间的对应关系表。



2.歌谱

3.建立步骤

(1)先把乐谱的音符找出,然后根据表2-15给出的定时值按乐谱的音符顺序建立编码表TABLE。

定时值为十六进制4位数,拆开分为两组,如5对应的定时值为FD80H,拆分为FDH和80H两组。前组装入定时器的高位TH0,后组装入定时器的低位TL0。程序中将进行两次查表来完成一个音符对应的定时初值的装入。

(2)在程序中使用定时器T0方式1来产生歌谱中各音符对应频率的音频脉冲,由 P3.4输出,再经三极管将信号放大后驱动蜂鸣器发出不同音节的声音。

(3)程序中节拍的控制是通过调用延时子程序DELAY的次数来实现的,1拍为 748 ms,即需要调用4次DELAY;3/4拍需要调用3次DELAY;2/4拍需要调用2次DELAY。

(4)节拍的控制码在表TABLE中位于音符码的后面。如第1行“DB 0FDH,80H, 03H,…”中,0FDH和80H是音符5的音符码,其后边的03H是节拍码,即3/4拍的时间。

(5)当一个音符的发音时间到时,再查下一个音符的定时常数和延时常数。依此进行下去,就可演奏出悦耳动听的乐曲。

2.11.2 程序设计

1.流程图

程序设计流程如图2-18所示。

2.程序

汇编语言编写的歌曲演奏源程序FS03.ASM代码如下:

01:          ORG           00H                ;主程序起始地址
02:          JMP           START              ;跳转至主程序
03:          ORG           0BH                ;定时器T0中断入口
04:          JMP           EXT0               ;跳转至T0中断子程序
05:  START:  MOV           TMOD,#00000001B    ;设置T0方式1
06:          MOV           IE,#10000010B      ;允许T0中断
07:          MOV           DPTR, #TABLE       ;存表首地址
08:  LOOP:   CLR           A                  ;清0
09:          MOVC          A,@A + DPTR        ;查表
10:          MOV           R1, A              ;定时器高8位存入R1
11:          INC           DPTR               ;指针加1
12:          CLR           A                  ;清0
13:          MOVC          A,@A + DPTR        ;查表
14:          MOV           R0, A              ;定时器低8位存入R0
15:          ORL           A, R1              ;进行或运算
16:          JZ            NEXT0              ;全0为休止符
17:          MOV           A, R0
18:          ANL           A, R1              ;进行与运算
19:          CJNE          A, #0FFH, NEXT     ;全1表示乐曲结束
20:           JMP           START              ;从头开始循环演奏
21:  NEXT:    MOV           TH0, R1            ;装入高位定时值
22:           MOV           TL0, R0            ;装入低位定时值
23:           SETB          TR0                ;启动定时器T0
24:           JMP           NEXT1              ;跳转到NEXT1处
25:   NEXT0:  CLR           TR0                ;关闭定时器,停止发音
26:   NEXT1:  CLR           A                  ;清0
27:          INC           DPTR               ;指针加1
28:          MOVC          A, @A + DPTR       ;查延时常数
29:          MOV           R2, A              ;延时常数存入R2
30:  LOOP1:  ACALL         DELAY              ;调用延时子程序
31:          DJNZ          R2, LOOP1          ;控制延时次数
32:          INC           DPTR               ;指针加1
33:          JMP           LOOP               ;跳转到LOOP处
34:  EXT0:   MOV           TH0, R1            ;重装定时值
35:          MOV           TL0, R0
36:          CPL           P3.4               ;反相输出
37:          RETI                             ;中断子程序返回
38:  DELAY:  MOV           R7, #02            ;延时187ms子程序
39:  D2:     MOV           R6, #187
40:  D3:     MOV           R5, #248
41:          DJNZ          R5,$
42:           DJNZ          R6, D3
43:           DJNZ          R7, D2
44:           RET                               ;延时子程序返回
45:   TABLE:  DB  0FDH,80H,03H, 0FDH,80H,01H     ;编码表
46:           DB  0FDH,0C6H,04H, 0FDH,80H,04H
47:           DB  0FEH,2AH,04H, 0FEH,02H,04H
48:           DB  00H,00H,04H
49:           DB  0FDH,80H,03H, 0FDH,80H,01H
50:           DB  0FDH,0C6H,04H, 0FDH,80H,04H
51:           DB  0FEH,5CH,04H, 0FEH,2AH,04H
52:           DB  00H,00H,04H
53:           DB  0FDH,80H,03H, 0FDH,80H,01H
54:           DB  0FEH,0C0H,04H, 0FEH,84H,04H
55:           DB  0FEH,2AH,04H, 0FEH,02H,04H
56:           DB  0FDH,0C6H,04H
57:           DB  0FEH,98H,03H, 0FEH,98H,01H
58:          DB  0FEH,84H,04H, 0FEH,2AH,04H
59:          DB  0FEH,5CH,04H, 0FEH,2AH,04H
60:          DB  00H,00H,04H
61:          DB  0FFH,0FFH                   ;结束码
62:          END                             ;程序结束

2.11.3 代码详解

1.标号说明

START:程序开始的进入点。

LOOP:处理下一个音符的进入点。

NEXT:装入定时初值的进入点。

NEXT0:关闭定时器、停止发音的进入点。

NEXT1:查找延时常数的进入点。

LOOP1:处理节拍时间的进入点。

EXT0:中断子程序的进入点。

DELAY:延时180ms子程序的进入点。

2.寄存器使用分配情况

R0、R1、R2、R5、R6、R7:普通寄存器。其中R0存放低位定时器初值;R1存放高位定时器初值;R2存放延时常数值;R5、R6和R7在延时子程序中作计数器用。

A和DPTR:特殊功能寄存器,其中A又称累加器,DPTR为数据指针。在程序中把表TABLE的首地址存入DPTR作基础地址,A作为变址寄存器。将基址寄存器和变址寄存器的内容相加(@A + DPTR)形成操作数的地址。

TMOD:定时器工作模式控制寄存器。

TL0和TH0:定时器0的计数器,TL0为低8位,TH0为高8位。

TR0:定时器0控制寄存器TCON的一个控制位。

IE:中断允许控制寄存器。

P3.4:对内是P3寄存器的一个位,对外是输入/输出端口的一个引脚,作音频信号输出端口。

3.程序分析解释

01~04:设定入口地址。其中定时器中断是从标号EXT0处进入中断子程序。

05~07:设置定时器T0为方式1,并允许T0中断。其中07行语句将表TABLE的首地址存入数据指针寄存器DPTR中。

08~10:第一次查表,取出表中的第一个码,即乐谱中的第一个音符5的定时常数(定时初值)FD80H中的高位部分FDH,并存入寄存器R1中。

11~14:第二次查表,取出表中的第二个码,即乐谱中的第一个音符5的定时常数FD80H中的低位部分(即80H),并存入寄存器R0中。

15~20:判断、转移语句。对二次查取到的码,检查是否有休止符码,该判断是通过第15行语句“ORL A,R1”对A和R1寄存器的内容进行或运算实现的。

如果累加器A中的值是00H,R1寄存器的值也是00H,进行或运算后再存入累加器A中,此时累加器A中的值是全0,说明取到的是休止符码。通过第16行语句“JZ NEXT0”,跳转至标号NEXT0处,关闭定时器,停止发音,完成乐谱中休止符的作用。

取码时是否取到了结束码是通过第18行语句指令ANL对A和R1进行与运算来判断的。如果累加器A中的值是FFH,R1寄存器的值也是FFH,进行与运算后再存入累加器A中,此时累加器A中的值是全1,说明取到的是结束码。

第19行语句“CJNE A,#0FFH,NEXT”,如果累加器A中的值与#0FFH不相等,则跳转移到NEXT处,开始向定时器装入定时常数;如果A与#0FFH相等,说明取到的码是结束码,程序向下执行,即从头开始循环演奏。

21~23:开始向定时器装入定时常数并启动定时器工作。

24~25:处理拍节。

26~29:查取延时码并存入R2。

30~31:决定拍节时间。如果取来的码是02H,程序调用两次DELAY延时,即为2/4拍节时间;如果取来的码是04H,程序调用4次DRLAY延时,即为1拍节时间。

32~33:每次查表取码后,数据指针都要加1,以便指向下一个待查的码。第33行语句将程序运行跳转到标号LOOP处,处理下一个音符。

34~37:中断子程序。当定时器计时满后将产生中断,由标号EXT0处进入中断子程序。在中断子程序中重装定时值,并通过第36行语句在P3.4端口输出音频信号。

38~44:延时187ms子程序。

45~61:编码表TABLE。在表中每个音节由3个码组成,前两个为音符码,后一个为节拍码。如表中第1行“0FDH,80H,03H”,其中0FDH和80H即为FD80H,是音符5的发音编码;03H是节拍码,3/4节拍。

表中的最后一行“0FFH,0FFH”是结束码,表示乐曲演奏结束。
4.边用边学指令

本程序用到新的指令有ORL和JZ。

 ORL:逻辑运算及位移类指令中的按位或操作指令。该指令将累加器A中的内容与源操作数所指出的内容按位进行逻辑或运算,结果存入A中。
 JZ:控制转移类指令,功能是当累加器A为0时跳转。

2.11.4 模拟仿真

1.模拟仿真前注意事项

在23与24行语句之间,加一条“SETB TF0”语句,该语句使定时器T0的溢出标志位TF0为1,模拟产生中断,使程序能进入中断子程序中运行。

在39~43行语句的前边加分号,使延时子程序的延时时间缩短为2ms,缩短模拟仿真时间。

2.模拟仿真中注意事项

观察程序主要运行路线:第一次查表→第二次查表→中断子程序及返回→第三次查 表→进入延时子程序及返回→处理下一个音符(跳转到LOOP处)。

观察累加器A中值的变化。第一次查表执行第09行语句“MOVC A,@A + DPTR”后,A值为FDH。第二次查表,执行第13行语句“MOVC A,@A + DPTR”后,A值为80H。两次查表取回音符5的对应码FD80H。第三次查表,执行第28行语句“MOVC A,@A + DPTR”后,A值为03H,取回的是音符5的对应拍节码。

2.11.5 实例测试

将写入歌曲演奏程序的单片机插入实验板插座内,并检查实验板上蜂鸣器接口是否与程序中声音输出端口一致,当检查无误后接通电源,就会听到生日快乐歌。

2.11.6 经验总结

在用单片机作可编程乐曲演奏器的程序里,一般用定时器T0方式1来控制音符的频率,调用延时子程序DELAY来控制节拍。

程序采用查表的方法,将乐谱转换成控制码并制成表TABLE,然后进行三次查表。第一、第二次查表完成对音符的控制,第三次查表读取节拍码,完成对节拍的控制。

在完成第一、第二次查取音符的控制码后,程序中还设有判断语句,如果判断出取来的是休止符码,就将定时器关闭一段时间;如果判断出取来的是结束码,程序就从头开始循环。

时间: 2024-10-20 22:51:20

《51单片机应用开发从入门到精通》——2.11 歌曲演奏实例的相关文章

《51单片机应用开发从入门到精通》——2.4 延时时间计算实例

2.4 延时时间计算实例 51单片机应用开发从入门到精通 在单片机的实时控制系统中,常常需要用到延时操作,所以,延时子程序往往是编写单片机程序中不可缺少的一部分.延时方法有硬件延时和软件延时,硬件延时将在后面有关章节中介绍,本节将介绍软件延时方法. 所谓软件延时,就是让计算机重复执行一些无具体任务的程序,利用执行程序的时间来达到延时的目的. 2.4.1 机器周期和指令周期 单片机读.写操作都需要消耗一定的时间,机器周期是指单片机完成一个基本操作所用的时间,如读操作.写操作等.当石英晶体为12MH

《51单片机应用开发从入门到精通》——2.9 交通灯实例

2.9 交通灯实例 51单片机应用开发从入门到精通 定时器/计数器是单片机中最常用.最重要的功能模块之一,本节通过交通灯控制器实例来演示定时器的使用方法,并复习如何使用上节学习的散转程序. 本节首先介绍交通灯的基础知识以及定时器/计数器的基础知识,接着介绍本实例的硬件电路构成,然后逐步分析定时器的编程以及程序的全貌,最后将总结一下本实例的技巧与注意点. 2.9.1 基础知识 交通灯控制器实例主要使用了8051单片机的定时器/计数器,本实例的基础知识主要包括:交通灯的变化规律.定时器/计数器的概念

《51单片机应用开发从入门到精通》——2.10 变频报警实例

2.10 变频报警实例 51单片机应用开发从入门到精通 本实例是用软件延时方法实现变频振荡报警,即用P3.4端口输出1kHz和2kHz的变频信号以示报警,每隔1s交替变换1次.本节硬件设计与上节相同. 2.10.1 程序设计 本程序利用软件延时方法,使P3.4端口输出1kHz和2kHz的变频信号,每隔1s交替变换1次. 1.流程图 程序设计流程如图2-16所示. 2.程序 汇编语言编写的变频报警源程序FS02.ASM代码如下: 01: MAIN: MOV R1,#8 ;1kHz持续时间 02:

《51单片机应用开发从入门到精通》——导读

前言 51单片机应用开发从入门到精通 随着微处理器技术和SoC技术的发展,从较早的4位机到8位机,一直发展到现在的32位机,单片机的应用逐渐渗透到生产.生活的各个领域.本书主要针对MCS-51体系单片机,从硬件.软件两个方面的基础知识开始进行介绍.MCS-51体系单片机由于具有简单易学.稳定性好.成本低等优点,在工业控制.家用电器.汽车电子乃至航天电子等许多领域都有着重要的应用. 本书主要针对初.中级读者群,通过众多的实例介绍单片机开发的基础知识.基本工具.基本过程及简单应用,既方便初学者入门,

《51单片机应用开发从入门到精通》——1.3 Keil uVision2集成开发环境

1.3 Keil uVision2集成开发环境 51单片机应用开发从入门到精通 uVision2 IDE是Keil software公司的产品,它集项目管理.编译工具.代码编写工具.代码调试以及完全仿真于一体,特别适用于个人开发或者人数少.对开发过程的管理还不成熟的开发团体.这一功能强大的软件提供简单易用的开发平台,可以让开发者在开发过程中集中精力于项目本身,加快开发速度. 1.3.1 uVision2介绍 uVision2的界面窗口如图1-13所示,该软件提供了丰富的工具,常用命令都具有快捷工

《51单片机应用开发从入门到精通》——1.5 测试方法和工具

1.5 测试方法和工具 51单片机应用开发从入门到精通 完成一个用户样机,首先要完成硬件组装工作,然后进入软件设计.调试和硬件调试阶段.硬件组装就是在设计.制作完毕的印制板上焊好元件与插座,然后就可用仿真开发工具进行软件设计.调试和硬件调试工作. 1.用户样机软件的设计.调试 用户样机软件设计.调试的过程如图1-25所示,可为以下几个步骤. 第一步,建立用户源程序.用户通过开发系统的键盘.CRT显示器及开发系统的编辑软件,按照所要求的格式.语法规定,把源程序输入到开发系统中,并存在磁盘上. 第二

《51单片机应用开发从入门到精通》——2.1 简单点亮发光二极管实例

2.1 简单点亮发光二极管实例 51单片机应用开发从入门到精通 单片机最简单的实例之一就是点亮发光二极管(LED)闪烁.本节通过点亮1只发光二极管的实例来介绍单片机的I/O口操作. 本节首先介绍单片机I/O口结构的基础知识,接着介绍实例的硬件电路,然后给出了实例程序,最后将分析操作单片机的I/O口的技巧与注意点. 2.1.1 基础知识 8051单片机有4个并行I/O口:P0-P3.这4个I/O口中只有P0口是真正的双向口,P1-P3是准双向口,P3口还具有第二功能,为系统提供一些控制信号.4个并

《51单片机应用开发从入门到精通》——2.2 跑马灯实例

2.2 跑马灯实例 51单片机应用开发从入门到精通 在上一节点亮1只LED的基础上,让我们来看看如何控制多只LED实现跑马灯效果. 2.2.1 硬件电路图 本实例中,硬件电路和上一节的硬件电路相似,为了实现跑马灯,本实例电路连接了8只LED,原理电路图如图2-2所示. 2.2.2 软件程序设计 控制多只LED实现跑马灯效果可以有多种实现方式,下面给出其中两种,请对比这两种实现方式的优劣. 1.程序全貌 首先,使用上节学习的直接寻址位置1指令SETB bit和直接寻址位清0指令CLR bit控制P

《51单片机应用开发从入门到精通》——2.7 中断的控制及设置

2.7 中断的控制及设置 51单片机应用开发从入门到精通中断系统结构如图2-6所示,从图可见,中断控制的实质是对4个特殊功能寄存器TCON.SCON.IE和IP进行管理和控制.只要按照人们的要求对这些寄存器的相应位进行设置(存入0或1,一般设置1为开通),就能完成对中断的有效管理和控制. 2.7.1 中断允许控制寄存器IE 1.IE的格式及位的含义寄存器IE的地址为A8H,作用是控制各中断源的开放与关闭.它实行两级控制,IE中有个总的控制位EA,当EA = 0时,屏蔽所有的中断请求:而当EA =

《51单片机应用开发从入门到精通》——2.12 电子琴

2.12 电子琴 51单片机应用开发从入门到精通本实例是采用44矩阵式键盘设计出16个音符,随意弹奏. 2.12.1 硬件设计 电子琴电路设计如图2-19所示. 单片机P3为输入端口,接有44矩阵式键盘,键盘上标出16个音符.键盘的4条行线的一端与单片机P3端口的P3.0.P3.1.P3.2和P3.3口相接,另一端通过上拉电阻接到 + 5V上:4条列线的一端与P3端口的P3.4.P3.5.P3.6和P3.7口相接.单片机的P2.4端口为输出端,通过限流电阻R1与三极管基极相接,三极管的集电极接有