实战:用单片机演奏音乐

来源:互联网 发布:淘域名市场 编辑:程序博客网 时间:2024/04/28 16:18

用单片机演奏音乐大概是每一个单片机爱好者都感兴趣的一个问题。在这节课中我们将要学习如何实现它。希望通过这个一个有趣的问题的解决进一步培养大家对单片机的兴趣,同时加深大家所学知识的理解以及逐步形成综合应用所学知识的能力。同时希望通过我的展示,同学们能从中体会解决问题的方法并把它应用到以后的学习、工作中。好吧,让我们开始。

一、     问题描述

利用单片机的I/O功能,外接一个蜂鸣器,使它发出一段简单的音乐。

二、    分析问题

也许刚听到这个问题,大家第一感觉就是太难了,我不可能做得出来。但是我告诉你们,你错了,其实你们都可以做到。为什么我敢这么说呢?因为其中用到的知识你们都已经学过或者知道的很基本的知识。那么你们欠缺的是什么呢?思考!分析问题你们凭直觉的认为难。好吧,让我们来分析一下问题,看看到底难不难:

思路:任何一个复杂的问题我们都可以顺着大而化小,分而治之的思路去解决它。

首先任何一个单片机系统的设计都分为两个方面:如何连接硬件、软件编制。因此我们根据问题的特点从这两个方面来讨论:

1.  硬件设计

摆在我们面前的首要问题是:为了让单片机唱歌需要什么样的元器件?然后是:单片机唱歌的基本原理是什么?如何连接我们选择的元件?

一、需要什么关键元件:单片机和蜂鸣器

二、单片机唱歌的基本原理:

首先回顾,什么是声音呢?声音是空气的振荡,不同的振荡频率我们就可以听到不同声调的声音。音的频谱范围约在几十到几千赫兹。

其次,如何让蜂鸣器发声?蜂鸣器有很多种类,但大致分为两类:有源式(直流电就发声,但频率单一);有源式(根据输入方波频率而发出不同的声音)。

我们选择哪一类的蜂鸣器?——无源式!

 

好了,在上面这些基本问题解决后,现在应该可以想到让单片机唱歌的基本原理了。利用程序来控制单处机某个口线出一定频率的方波到蜂鸣器,蜂鸣器就可以发出一定音调的声音,若再利用不同的延时程序改变输出频率,就可以改变音调,进而就可让单片机发出“1”、“2”,“3”,“4”,“5”,“6”,“7”的音乐。




单片机输出方波的方法我们已经知道了——控制口线“高”、“低”电平的持续时间。于是设计电路如下:

 

好了,我们完成了硬件设计,简单吗?下面我们来看软件设计。

2.  软件设计

我们已经编制过在某一口线输出方波的程序了,我们通过软件延时或者定时器延时来的方式以不同频率改变口线的的高低电平状态来实现的。如果只是让蜂鸣器发声这已经够了。但是我们要的是唱歌,所以还有一点工作需要作。我们来看看有哪些工作。

一、音调:输出不同频率的方波,以实现1234等的不同音调;

比如,发出200HZ的音频,其周期为1/200秒,即5ms。这样,当 P3.2的高电平或低电平的持续时间为2.5ms时,就能发出200HZ的音调。我们可以写一个延时子程序,用R3来提供参数,R3=1时,延时为20us,那么R32500/20=1257DH)时,就可以发出200Hz的音调,提供不同的R3常数,可以得到不同的音调变化。附表给出了不同音阶对应的频率。

 

二、节拍:控制一个音符输出的时间,比如1拍、1/4拍。

仅上所叙还不够,要准确奏出一首曲子,必须准确地控制乐曲节奏,即一音符的持续时间。例如,一首曲子的节奏为每分种94拍,那么一拍就为60/94=0.64秒。

音乐的节拍我们可用定时器来控制,简单的说,一个一拍的音符唱0.64秒,我们就设置一个定时器定时0.64秒,时间一到就换下一个音符。

但是,由于单片机的T0,在12MHz晶振下最大定时时间只能为65毫秒,因此不可能直接用改变T0的时间初值来实现不同节拍。如何定时一个更大的时间,上节课我们已经讲了一个方法。我们可以用T0来产生10毫秒的时间基准,然后设置 一个中断计数器,通过判别中断计数器的值来控制节拍时间的长短。表2中也给出了各种节拍所对应的时间常数。例如对1/4拍音符,定时时间为0.16秒,相应的时间常数(中段计数器)为16(即10H);对3拍音符,定时时间为1.92秒,相应时间长数为192(即C0H)。

三、     实现

因为一首曲子不止一个音符,我们不可能对每一个音符的音阶都去“手工”的提供时间常数,为了实现的简化,我们编制一个将每一音符的时间常数和其相应的节拍常数作为一组,按顺序将乐曲中的所有常数排列成的表格,在程序里用查表指令依次查出每一个音符的频率和对应节拍时间,产生音符并控制节奏,就可以实现演奏效果。

此外,结束符和体止符可以分别用代码00HFFH来表示,若查表结果为00H,则表示曲子终了;若查表结果为FFH,则产生相应的停顿效果。

好了,思路已经形成,下面就可以将其实现出来了:

1.    程序流程图:

这个程序包括一个定时器中断,一个延时子程序,以及一个输出方波的程序。这些小程序我们都已经写过了,现在的任务是把他们综合起来。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.    程序代码:(以下代码奏出八月桂花香这首曲子)

       ORG     0000H

       LJMP    START

       ORG     000BH

       INC      20H                      ;中断服务,中断计数器加1

       MOV     TH0,       #0DBH

       MOV     TL0,       #0FFH          ;11.0592M晶振,形成10毫秒中断

       RETI

START:   MOV     SP,   #50H

       MOV     TH0,       #0DBH

       MOV     TL0,       #0FFH

       MOV     TMOD,   #01H

       MOV     IE,   #82H

MUSIC0: NOP

       MOV     DPTR,    #DAT           ;表头地址送DPTR

       MOV     20H,       #00H                   ;中断计数器清0

MUSIC1: NOP

       CLR      A                                ;A清零

       MOVC  A,    @A+DPTR          ;查表取代码

       JZ  END0                                 ;00H,则结束

       CJNE    A,    #0FFH,   MUSIC5  ;如果不是休止符,往下执行,

;R6作为音符频率控制,唱R7节拍那么久。

       LJMP    MUSIC3

MUSIC5: NOP

       MOV     R6,  A                        ;R6=18H音符的频率

       INC      DPTR                         ;DPTR1

       MOV     A,    #0

       MOVC  A,    @A+DPTR          ;取节拍代码送R7

       MOV     R7,A                           ;R7=30H音符发音的时间

       SETB    TR0                            ;启动计数

MUSIC2: NOP

       CPL      P3.2                            ;P3.2是音乐输出引脚

       MOV     A,    R6

       MOV     R3,  A                          ;R3=R6=18H

       LCALL  DEL

       MOV     A,    R7

       CJNE    A,    20H,       MUSIC2        ;中断计数器(20H)=R7?;不等,则继续循环

       MOV     20H,       #00H                   ;等于,则取下一代码

       INC      DPTR

       LJMP    MUSIC1

MUSIC3: NOP                                  ;休止100毫秒

       CLR      TR0

       MOV     R2,  #0DH                    ;R2=13

MUSIC4: NOP

       MOV      R3,  #0FFH                 ;R3=255

       LCALL  DEL

       DJNZ    R2,  MUSIC4

       INC      DPTR

       LJMP    MUSIC1

END0:     NOP

       MOV     R2,  #0FFH          ;歌曲结束,延时1秒后继续

MUSIC6:

       MOV     R3,  #00H

       LCALL  DEL

       DJNZ    R2,  MUSIC6

       LJMP    MUSIC0

DEL:       NOP

DEL3:     MOV     R4,  #02H             

DEL4:     NOP

       DJNZ    R4,  DEL4

       NOP

       DJNZ    R3,  DEL3

       RET

       NOP

DAT:

DB 18H, 30H, 1CH, 10H, 20H, 40H, 1CH, 10H

DB 18H, 10H, 20H, 10H, 1CH, 10H, 18H, 40H

DB 1CH, 20H, 20H, 20H, 1CH, 20H, 18H, 20H

DB 20H, 80H, 0FFH, 20H,30H, 1CH, 10H, 18H

DB 20H, 15H, 20H, 1CH, 20H, 20H, 20H, 26H

DB 40H, 20H, 20H, 2BH, 20H, 26H, 20H, 20H

DB 20H, 30H, 80H, 0FFH,20H, 20H, 1CH, 10H

DB 18H, 10H, 20H, 20H, 26H, 20H, 2BH, 20H

DB 30H, 20H, 2BH, 40H, 20H, 20H, 1CH, 10H

DB 18H, 10H, 20H, 20H, 26H, 20H, 2BH, 20H

DB 30H, 20H, 2BH, 40H, 20H, 30H, 1CH, 10H

DB 18H, 20H, 15H, 20H, 1CH, 20H, 20H, 20H

DB 26H, 40H, 20H, 20H, 2BH, 20H, 26H, 20H

DB 20H, 20H, 30H, 80H, 20H, 30H, 1CH, 10H

DB 20H, 10H, 1CH, 10H, 20H, 20H, 26H, 20H

DB 2BH, 20H, 30H, 20H, 2BH, 40H, 20H, 15H

DB 1FH, 05H, 20H, 10H, 1CH, 10H, 20H, 20H

DB 26H, 20H, 2BH, 20H, 30H, 20H, 2BH, 40H

DB 20H, 30H, 1CH, 10H, 18H, 20H, 15H, 20H

DB 1CH, 20H, 20H, 20H, 26H, 40H, 20H, 20H

DB 2BH, 20H, 26H, 20H, 20H, 20H, 30H, 30H

DB 20H, 30H, 1CH, 10H, 18H, 40H, 1CH, 20H

DB 20H, 20H, 26H, 40H, 13H, 60H, 18H, 20H

DB 15H, 40H, 13H, 40H, 18H, 80H, 00H

END


--------------------------------------------------------------------

感谢网上的大虾提供这样的资料,我这篇文章只是根据网上已有的文章稍加整理编写出的教案


原创粉丝点击