zoukankan      html  css  js  c++  java
  • 【网络收录】基于51单片机开发音乐播放器

    【网络收录】基于51单片机开发音乐播放器


    本文作者:天析

    作者邮箱:2200475850@qq.com

    发布时间: Thu, 22 May 2014 18:14:00 +0800

    特别声明:本资料来源于网络,北极边界安全团队不享有本作品的相应版权,如有侵权问题请在下方留言或联系 QQ:2200475850 进行删除处理!
    本资料来源时间:2014年5月22日

    一、概述:

    现当今,单片机的应用无处不在。利用单片机控制的万年历也多不胜举。时钟芯片也相当之多,而利用单片机存储音乐,控制播放最为广泛。它有功能多﹑价格优﹑外围电路简单的特点,备受音乐爱好者及音乐芯片制造商的青昧。本实验,用80C51单电机及少数外围实现音乐播放器功能,并伴有彩灯闪烁。
    C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能。此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。因此,使用C语言进行程序设计已成为软件开发的一个主流。C语言来编写目标系统软件,会大大缩短开发周期,且明显地增加软件的可靠性,便于改进和扩展,从而研制出规模更大、性能更完备的系统。因此,用C语言进行8051单片机程序设计是单片机开发与应用的必然趋势。
    设计时采用Keil C软件编程,用protues软件仿真,核心器件采用灵活性高且价格低廉的AT89C51芯片。设计完成后系统可播放自编歌曲,同时发光二极管随着歌曲的不同而闪烁。

    本课程设计的目的是学习运用C语言开发单片机应用软件,了解为将来从事单片机应用系统的开发打下坚实的基础。

    二、实验目的:

    (1).强化、加大深度和扩大单片机应用的知识面,提高综合及灵活运用所学知识解决工业控制的能力; 
    (2).培养针对课题需要,选择和查阅有关手册、图表及文献资料的自学能力,提高组成系统、编程、调试的下手能力; 
    (3).过对课题设计方案的分析、选择、比较、熟悉单片机用系统研发、研制的过程,软硬件设计的方法、内容及步骤。

    三、实验设计:

    3.1、设计电路图:
    1
    3.2、设计思路:
    总体原理:
    乐曲中不同的音符,实质就是不同频率的声音。通过单片机产生不同的频率的脉冲信号,经过放大电路,由蜂鸣器放出,就产生了美妙和谐的乐曲。
    片机产生不同频率脉冲信号的原理:
    (1)要产生音频脉冲,只要算出某一音频的脉冲(1/频率),然后将此周期除以2,即为半周期的时间,利用定时器计时这个半周期的时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期的时间再对I/O反相,就可以在I/O脚上得到此频率的脉冲。
    (2)利用8051的内部定时器使其工作在计数器模式MODE1下,改变计数值TH0及TL0以产生不同频率的方法如下
    例如,频率为523Hz,其周期天/523 S=1912uS,因此只要令计数器计时956uS/1us=956,在每计数956次时就将I/O反接,就可得到中音DO(532Hz)。
    计数脉冲值与频率的关系公式如下:
    N=Fi/2/Fr 
    (N:计数值,Fi:内部计时一次为1uS,故其频率为1MHz,Fr:要产生的频率 )
    (3) 其计数值的求法如下:
    T=65536-N=65536-Fi/2/Fr
    计算举例:
    设K=65536,F=1000000=Fi=1MHz,求低音DO(261Hz)、中音DO(523Hz)、高音DO(1046Hz)的计数值。
    T=65536-N=65536-Fi/2/Fr=65536-1000000/2/Fr=65536-500000/Fr
    低音DO的T=65536-500000/262=63627
    中音DO的T=65536-500000/523=64580
    高音DO的T=65536-500000/1047=65059
    (4)C调个音符频率与计数值T的对照表如下表所示:

    2

    (5)每个音符使用1个字节,字节的高4位代表音符的高低,低4位代表音符的节拍,下表为节拍码的对照。但如果1拍为0.4秒,1/4拍是0.1秒,只要设定延迟时间就可求得节拍的时间。假设1/4节拍为1DELAY,则1拍应为4DELAY,以此类推。所以只要求得1/4拍的DELAY时间,其余的节拍就是它的倍数,如下表为1/4和1/8节拍的时间设定。

    (6)移调

    一般的歌曲,有3/8、2/4、3/4、4/4等节拍类型,但不管有几拍,基本上是在C调下演奏的。如果是C调,则音名C唱Do,音名D唱Re,音名E唱Mi,音名E唱Mi,音名F唱Fa,音名G唱So,音名A唱La,音名B唱Ti等。但是,并不是所有的歌曲都是在C调下演奏的,还有D调、E调、F调、G调等。D调是将C调各音符上升一个频率实现的,即C调下的音名D在D调下唱Do,C调下的音名E在D调下唱Re,C大调的音名F在D调下上升高半音符F#唱Mi,C调下的音名G在D调下唱Fa,C调下的音名C在D调下上升高伴音C#符唱Ti。这种唱法称为移调。
    3.3、音乐代码库的建立方法:
    (1)先找出乐曲的最低音和最高音范围,然后确定音符表T的顺序。
    (2)把T值表建立在TABLE1,构成发音符的计数值放在“TABLE”。
    (3)简谱码(音符)为高位,节拍为(节拍数)为低4位,音符节拍码放在程序的“TABLE”处。
    (4)音符节拍码00H为音乐结束标记。
    3.4、实验器件介绍:
    AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS 8位微处理器,俗称单片机。AT89C2051是一种带2K字节闪烁可编程可擦除只读存储器的单片机。单片机的可擦除只读存储器可以反复擦除100次。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。AT89C单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。外形及引脚排列如图所示

    主要特性:
    •与MCS-51 兼容 
    •4K字节可编程闪烁存储器 
    •寿命:1000写/擦循环
    •数据保留时间:10年
    •全静态工作:0Hz-24MHz
    •三级程序存储器锁定
    •128×8位内部RAM
      •32可编程I/O线
    •两个16位定时器/计数器
    •5个中断源 
    •可编程串行通道
    •低功耗的闲置和掉电模式
    •片内振荡器和时钟电路
    管脚说明:
    VCC:供电电压。
    GND:接地。
    P0口:P0口为一个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口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
    P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
    P3口也可作为AT89C51的一些特殊功能口,如下所示

    P3口被选功能

      口管脚 备选功能
      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:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。
    /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
    /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
    XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
    XTAL2:来自反向振荡器的输出。
    芯片擦除:
    整个PEROM阵列和三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚处于低电平10ms 来完成。在芯片擦操作中,代码阵列全被写“1”且在任何非空存储字节被重复编程以前,该操作必须被执行。
    此外,AT89C51设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。在闲置模式下,CPU停止工作。但RAM,定时器,计数器,串口和中断系统仍在工作。在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为止。

    四、调试与仿真

    Keil C51单片机软件开发系统:

    1. 系统的整体结构
      C51工具包的整体结构中,其中uVision与Ishell分别是C51 for Windows和for Dos的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。然后分别由C51及A51编译器编译生成目标文件(.OBJ)。目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
    2. 采用KEIL 开发的89c51单片机应用程序步骤:
      (1)在uVision 集成开发环境中创建新项目(Project),扩展文件名为.UV2,并为该项目选定合适的单片机CPU器件(本设计采用ATMEL 公司下的AT89C51)

    (2)用uVision 的文本编辑器编写源文件,可以是汇编文件(.ASM),也可以使C语言文件(扩展名.C),并将该文件添加到项目中去。一个项目文件可以包含多个文件,除了源程序文件外,还可以是库文件、头文件或文本说明文件。
    (3)通过uVision 2 的相关选择项,配置编译环境、连接定位器以及Debug调试器的功能。
    (4)对项目中的源文件进行编译连接,生成绝对目标代码和可选的HEX文件,如果出现编译连接错误则返回到第2步,修改源文件中的错误后重构整个项目。
    (5)对没有语法错误的程序进行仿真调试,调试成功后将HEX文件写入到单片机应用系统的ROM中。

    Proteus的操作:
    1.硬件电路图的接法操作 :
    (1).放置选择(删除)元器件
    (2).移动元器件
    (3).缩放视图
    (4).连接导线
    (5).仿真,调试

    1. 单片机系统PROTEUS设计与仿真过程:
      Proteus强大的单片机系统设计与仿真功能,使它可成为单片机系统应用开发和改进手段之一。全部过程都是在计算机上通过Proteus来完成的。其过程一般也可分为三步:

    (1)在ISIS平台上进行单片机系统电路设计、选择元器件、接插件、连接电路和电气检测等。简称Proteus电路设计。
    (2)在Keil平台上进行单片机系统程序设计、编辑、汇编编译、代码级调试,最后生成目标代码文件(*.hex)。简称Proteus源程序设计和生成目标代码文件。
    (3)在ISIS平台上将目标代码文件加载到单片机系统中,并实现单片机系统的实时交互、协同仿真。它在相当程度上反映了实际单片机系统的运行情况。简称Proteus仿真。

    五、源程序代码及注释

    /*-----------------------------------------------
      名称:音乐盒
      日期:2014.5.22 
    ------------------------------------------------*/
    #include<reg52.h>       
    /*------------------------------------------------
                     硬件端口定义
    ------------------------------------------------*/
    sbit SPK=P2^0;  //定义音乐输出端口
    sbit key1=P3^2; //定义按键 用于 暂停
    sbit key2=P3^3; //定义按键 用于 切换
    unsigned char W=0,T;    //用于选择音乐
    unsigned char Timer0_H,Timer0_L,Time;
    void delay5ms(void)   //误差 0us
    {
        unsigned char a,b;
        for(b=185;b>0;b--)
            for(a=12;a>0;a--);
    }
    void delay500ms(void)   //误差 0us
    {
        unsigned char a,b,c;
        for(c=205;c>0;c--)
            for(b=116;b>0;b--)
                for(a=9;a>0;a--);
    }
                         //世上只有妈妈好 数据表    音谱,高中低音,音长
    code unsigned char MUSIC[102]={       6,2,3,      5,2,1,      3,2,2,    5,2,2,    1,3,2,    6,2,1,    5,2,1,
                                          6,2,4,      3,2,2,      5,2,1,    6,2,1,       5,2,2,     3,2,2,       1,2,1,
                                          6,1,1,      5,2,1,      3,2,1,     2,2,4,       2,2,3,     3,2,1,    5,2,2,
                                          5,2,1,      6,2,1,      3,2,2,     2,2,2,    1,2,4,     5,2,3,       3,2,1,
                                          2,2,1,      1,2,1,      6,1,1,     1,2,1,       5,1,6,     0,0,0 
                                          };
                        //送别 数据表    音谱,高中低音,音长
    code unsigned char MUSIC1[174]={    5,2,2,        3,2,1,        5,2,1,        1,3,4,    
                                        6,2,2,        1,3,2,                                            
    5,2,4,
                                    5,2,2,        1,2,1,         
    2,2,1,        3,2,2,        2,2,1,        1,2,1,
                                    2,2,8,
                                    5,2,2,        3,2,1,         
    5,2,1,        1,3,3,        7,2,1,
                                    6,2,2,        1,3,2,         
    5,2,4,
                                    5,2,2,        2,2,1,         
    3,2,1,        4,2,3,        7,1,1,
                                    1,2,8,
                                    6,2,2,        1,3,2,         
    1,3,4,
                                    7,2,2,        6,2,1,         
    7,2,1,        1,3,4,
                                    6,2,1,        7,2,1,         
    1,3,1,        6,2,1,        6,2,1,        5,2,1,        3,2,1,        1,2,1,
                                    2,2,8,
                                    5,2,2,        3,2,1,         
    5,2,1,        1,3,3,        7,2,1,
                                    6,2,2,        1,3,2,         
    5,2,4,
                                    5,2,2,        2,2,1,         
    3,2,1,        4,2,3,        7,1,1,
                                    1,2,8
                                };
    
                        //新年好 数据表    音谱,高中低音,音长
    code unsigned char MUSIC2[90]={        1,2,1,        1,2,1,        1,2,2,        5,1,2,
                                    3,2,1,        3,2,1,         
    3,2,2,        1,2,2,
                                    1,2,1,        3,2,1,         
    5,2,2,        5,2,2,
                                    4,2,1,        3,2,1,         
    2,2,4,
                                    2,2,1,        3,2,1,         
    4,2,2,        4,2,2,
                                    3,2,1,        2,2,1,         
    3,2,2,        1,2,2,
                                    1,2,1,        3,2,1,         
    2,2,2,        5,1,2,
                                    7,1,1,        2,2,1,         
    1,2,4
                                };
    
                        //童年 数据表    音谱,高中低音,音长
     code unsigned char MUSIC3[423]={    5,1,1,        5,1,1,        3,1,1,        5,1,2,        3,1,1,        5,1,2,
                                    6,1,1,        6,1,1,        1,2,1,        6,1,2,        6,1,1,        1,2,2,
                                    2,2,1,        2,2,1,        3,2,1,        2,2,2,        5,1,1,        6,1,1,        5,1,1,
                                    1,2,1,        1,2,1,        5,1,1,        1,2,1,        1,2,1,        1,2,2,        1,2,1,
                                    1,2,1,        5,1,2,        1,2,1,        6,1,1,        5,1,1,        3,1,1,        2,1,1,
                                    1,1,2,        3,1,1,        5,1,1,        5,1,2,        5,1,1,        3,1,1,
                                    6,1,1,        6,1,1,        1,2,1,        6,1,1,        6,1,1,        6,1,1,        6,1,1,        5,1,1,
                                    1,2,2,        1,2,1,        1,2,1,        1,2,1,        6,1,1,        1,2,1,        6,1,1,
                                    5,1,2,        0,2,1,        3,1,1,        6,1,1,        1,2,1,        6,1,1,        5,1,1,
                                    3,1,1,        2,1,1,        3,1,1,        5,1,1,        5,1,2,        5,1,1,        3,1,1,
                                    6,1,1,        6,1,1,        1,2,1,        6,1,1,        6,1,1,        6,1,1,        6,1,1,        5,1,1,
                                    1,2,2,        1,2,1,        1,2,1,        1,2,1,        6,1,1,        6,1,1,        1,2,1,
                                    2,2,2,        0,2,1,        5,1,1,        2,2,1,        5,2,1,        2,2,2,
                                    5,2,1,        5,2,2,        5,2,1,        5,2,1,        5,2,1,        3,2,1,        2,2,1,
                                    1,2,1,        1,2,2,        6,1,1,        6,1,1,        1,2,1,        6,1,1,        1,2,1,
                                    2,2,1,        2,2,1,        2,2,1,        2,2,1,        2,2,1,        1,2,1,        3,2,1,        2,2,1,
                                    2,2,8,
                                    3,2,1,        3,2,2,        3,2,1,        3,2,2,        2,2,2,
                                    1,2,1,        1,2,2,        1,2,1,        2,2,1,        1,2,1,        6,1,1,        5,1,1,
                                    5,1,1,        5,1,2,        5,1,1,        6,1,1,        5,1,1,        2,2,1,        3,2,1,
                                    1,2,8,
                                    1,2,1,        5,1,2,        1,2,1,        6,1,1,        5,1,1,        3,1,1,        2,1,1,
                                    1,2,6,        0,2,2
                              };
    
                         // 音阶频率表 高八位
    code unsigned char FREQH[]={
                                0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 
                                0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
                                0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
                                0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
                               } ;
                         // 音阶频率表 低八位
    code unsigned char FREQL[]={
                                 0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
                                 0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
                                 0xEE,0x44, 0x6B,0xB4,0xF4,0x2D, 
                                 0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
                                };
    /*------------------------------------------------
     uS延时函数,含有输入参数 unsigned char t,无返回值
     unsigned char 是定义无符号字符变量,其值的范围是
     0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
     长度如下 T=tx2+5 uS 
    ------------------------------------------------*/
    void DelayUs2x(unsigned char t)
    {   
             while(--t);
    }
    /*------------------------------------------------
     mS延时函数,含有输入参数 unsigned char t,无返回值
     unsigned char 是定义无符号字符变量,其值的范围是
     0~255 这里使用晶振12M,精确延时请使用汇编
    ------------------------------------------------*/
    void DelayMs(unsigned char t)
    {    
        while(t--)
        {
             //大致延时1mS
            DelayUs2x(245);
        DelayUs2x(245);
        }
    }
    /*------------------------------------------------
                    节拍延时函数
     各调1/4节拍时间:
     调4/4  125ms
     调2/4  250ms
     调3/4  187ms
    ------------------------------------------------*/
    void delay(unsigned char t)
    {
        unsigned char i;
        for(i=0;i<t;i++)
            DelayMs(250);
        TR0=0;
    }
    /*------------------------------------------------
               定时器0中断
    ------------------------------------------------*/
    void TIM0_ISR() interrupt 1
    {
        TR0=0;      
        SPK=!SPK;
        TH0=Timer0_H;
        TL0=Timer0_L;
        TR0=1;
    }
    /*------------------------------------------------
                    歌曲处理函数
    ------------------------------------------------*/
    void Song()
    {
        TH0=Timer0_H;//赋值定时器时间,决定频率
        TL0=Timer0_L;
        TR0=1;       //打开定时器
        delay(Time); //延时所需要的节拍                      
    }
    /*------------------------------------------------
                    主函数
    ------------------------------------------------*/
    void led(unsigned char a);
    
    void main(void)
    {
        unsigned int i;
        unsigned char k;
    TMOD|=0x01; //置定时器0工作方式1
    EA=1;       //打开全局中断
    ET0=1;      //打开 定时器0 中断
    
    EX0=1;        //打开 外部中断0 中断
    IT0=1;        //设置为下降沿中断
    
    EX1=1;        //打开 外部中断1 中断
    IT1=1;        //设置为下降沿中断
    PX1=1;        //设置 外部中断1 为高优先级
    
    while(1)
    {
        //i=0;
        
        if(W==0)
        {  
            T=W;
            for(i=0;i<100;i=i+3)
            {         //音乐数组长度 ,唱完从头再来
                led(MUSIC[i]);
            
                k=MUSIC[i]+7*MUSIC[i+1]-1;//去音符振荡频率所需数据
                Timer0_H=FREQH[k];
                Timer0_L=FREQL[k];
                Time=MUSIC[i+2];          //节拍时长
               // i=i+3;
                Song();
                if(T!=W)
                    break;
            }
        }
        
    
        if(W==1)
        {  
            T=W;
            for(i=0;i<174;i=i+3)
            {         //音乐数组长度 ,唱完从头再来
                led(MUSIC1[i]);
            
                k=MUSIC1[i]+7*MUSIC1[i+1]-1;//去音符振荡频率所需数据
                Timer0_H=FREQH[k];
                Timer0_L=FREQL[k];
                Time=MUSIC1[i+2];          //节拍时长
               // i=i+3;
                Song();
                if(T!=W)
                    break;
            }
        }
    
        if(W==2)
        {  
            T=W;
            for(i=0;i<90;i=i+3)
            {         //音乐数组长度 ,唱完从头再来
                led(MUSIC2[i]);
            
                k=MUSIC2[i]+7*MUSIC2[i+1]-1;//去音符振荡频率所需数据
                Timer0_H=FREQH[k];
                Timer0_L=FREQL[k];
                Time=MUSIC2[i+2];          //节拍时长
               // i=i+3;
                Song();
                if(T!=W)
                    break;
            }
        }
    
        
        if(W==3)
        {  
            T=W;
            for(i=0;i<423;i=i+3)
            {         //音乐数组长度 ,唱完从头再来
                led(MUSIC3[i]);
            
                k=MUSIC3[i]+7*MUSIC3[i+1]-1;//去音符振荡频率所需数据
                Timer0_H=FREQH[k];
                Timer0_L=FREQL[k];
                Time=MUSIC3[i+2];          //节拍时长
               // i=i+3;
                Song();
                if(T!=W)
                    break;
                }
            }
    
         } 
    }
    
    // 频谱函数
    void led(unsigned char a)    
    {
    switch(a)
    {
        case 0:P1=0xff;break;
        case 1:P1=0x7f;break;
        case 2:P1=0x7e;break;
        case 3:P1=0x7c;break;
        case 4:P1=0x78;break;
        case 5:P1=0x70;break;
        case 6:P1=0x60;break;
        case 7:P1=0x40;break;
        case 8:P1=0x00;break;
        }
    
    }
    
    //    外部中断0 中断服务程序    用于暂停
    void zhongduan0() interrupt 0
    {   
        delay5ms();    //按键去抖
        if(!key1)
                {
        while(!key1);    //松手检测
        while(key1&&T==W);    //检测按键是否按下
        delay5ms();    //按键去抖
        while(key1&&T==W);    //检测按键是否按下
        while(!key1&&T==W);    //松手检测
    }
    }
    
    //    外部中断1 中断服务程序
    void zhongduan1() interrupt 2
    {   
        delay5ms();    //按键去抖
    if(!key2)
    {
        if(W==3)
            W=0;
        else
            W++;
        while(!key2);    //松手检测
        delay500ms();
        
    }
    }
    

    五、板子外观

    3
    4

    六、设计及调试中的体会

    课程设计是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域,在生活中可以说得是无处不在。因此作为自动化专业的学生来说掌握单片机的开发技术是十分重要的。
    我的题目是音乐播放器硬软件的设计,对于我们这些工科学生来说,这是一次考验。怎么才能找到课堂所学与实际应用的最佳结合点?怎样让自己的业余更接近专业?怎样让自己的计划更具有序性,而不会忙无一用?这都是我们所要考虑和努力的。这次课程设计我学到很多很多的东西,学会了怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。不仅巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识,掌握了一种系统的研究方法,可以进行一些简单的编程。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
    同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,对单片机汇编语言掌握得不够好。这次课程设计通过自己的努力,同学的帮助,还有老师的辛勤指导下,最终顺利完成了。

  • 相关阅读:
    THUSC2021游记
    CF补题计划
    2020 Petrozavodsk Winter Camp Day5 简要题解
    很“炸”的安卓UI自动化工具
    SQL-关联查询
    MeterSphere接口自动化平台的使用
    Android开发Handler是如何确保UI刷新优先执行的源码解读
    android开发BadTokenException: Unable to add window -- token null is not valid; is your activity running?比较好的解决方法
    Android开发判断是否为鸿蒙系统
    Android性能优化使用自带的Profiler功能分析traceView文件
  • 原文地址:https://www.cnblogs.com/anbus/p/11303701.html
Copyright © 2011-2022 走看看