基于单片机的电子贺卡设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
引言 (2)
一、设计要求 (3)
1.1设计题目 (3)
1.2课题意义 (3)
二、系统硬件原理及设计 (3)
2.1系统组成框图 (3)
2.2电子贺卡的功能结构框图 (4)
三、音乐基础知识 (4)
3.1音乐基础 (4)
3.2音调脉冲和音乐节拍的实现 (5)
3.2.1 音调脉冲的产生 (5)
3.2.2音乐节拍的产生 (6)
3.2.3音符码表的编制 (7)
3.3主程序流程图 (9)
3.4发声模块程序设计 (10)
3.5按键模块程序设计 (11)
四、硬件电路设计 (12)
4.1主要器件 (12)
4.1.1 微处理器 (12)
4.1.2开关元件 (14)
4.2发声驱动电路 (15)
4.3电路工作原理 (16)
五、软件设计 (16)
5.1软件开发平台 (17)
5.2详细的程序设计 (17)
总结 (27)
参考文献 (28)
引言
如今,电子技术获得了飞速的发展,现代电子产品几乎渗透了社会的各个领域。
目前,单片机正朝着高性能个多品种方向发展趋势将是进一步想着CMOS化、低功耗、小体积、大容量、高性能、低价格和外围电路装化等几个方面发展。
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
相当于一个微型的计算机,和计算机相比,单片机只缺少了 I/O 设备。
概括的讲:一块芯片就成了一台计算机。
它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。
同时,学习使用单片机是了解计算机原理与结构的最佳选择。
单片机内部也用和电脑功能类似的模块,比如 CPU,内存,并行总线,还有和硬盘作用相同的存储器件,不同的是它的这些部件性能都相对我们的家用电脑弱很多,不过价钱也是低的,一般不超过 10元即可。
单片机具有体积小、功耗低、控制功能强、扩展灵活、微型化和使用方便等优点,广泛应用于仪器仪表中,结合不同类型的传感器,可实现诸如电压、功率、频率、湿度、温度、流量、速度、厚度、角度、长度、硬度、元素、压力等物理量的测量。
采用单片机控制使得仪器仪表数字化、智能化、微型化,且功能比起采用电子或数字电路更加强大。
例如精密的测量设备(功率计,示波器,各种分析仪)。
目前单片机渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。
因此,单片机的学习、开发与应用将造就一批计算机应用与智能化控制的科学家、工程师。
利用单片机实现音乐播放有很多要点,例如外部电路简单,控制方便等,因而备受广大单片机爱好者的喜爱。
通过音乐发声器的设计方案,掌握C语言的编程方法。
并熟练的运用 AT89C52 单片机定时器产生固定频率的方波信号,推动喇叭发出旋律,按下单键可以演奏预先设置的歌曲旋律,最重要的是自己还可以通过程序设计输入自己喜欢的歌曲来演奏,本设计采用简易音阶编码直觉式输入法方便设计音乐旋律。
一、设计要求
基于单片机的音乐播放器,播放简单歌曲,本次课题音乐播放为《奇异恩典》、《欢乐颂》和《生日快乐》。
1.1设计题目
基于单片机的电子贺卡设计
1.2课题意义
基于单片机的音乐播放器可应用于 mp3,MP4,扩音器等很多方面,并可作为很多系统的辅助功能,作为单片机的重要硬件资源之一,利用定时器可以产生各种固定频率的方波信号,也可以产生包括“Do”、“Re”、“Me”--等音阶在内的各种频率声音。
将各个音阶连接在一起,便可组成一支曲子或是演奏一段旋律。
我们可以运用在生活实际中比如贺卡或者电子门铃。
基于这个思想,我们设计了一款特殊的“音乐播放器”,本播放器可实现播放、暂停、等功能。
由于时间及条件限制,本设计实现了一种简单的音乐播放器,其核心器件采用 AT89C52 单片机,本播放器具有电路简单,功能强大,易于拓展等特点。
在此基础上,可以添加按键,LED 显示屏等模块,实现切换歌曲,歌名显示,动感音乐屏等功能。
二、系统硬件原理及设计
2.1系统组成框图
硬件系统包括主控模块、时钟电路、复位电路、电源电路、显示模块、发声模块和按键模块。
如图2-1所示。
图2-1 硬件系统结构图
2.2 电子贺卡的功能结构框图
电子贺卡的功能框图如图2-2所示,程序调用,按不同键负责控制歌曲的播放、下一曲、上一曲和暂停,同时蜂鸣器发出响声和停止声音。
图2-2 电子贺卡的功能框图
三、音乐基础知识
3.1 音乐基础
音作为一种物理现象,是由于物体振动而产生的,振动产生的声波作用
开始
播放、下
一曲、上一曲、暂停
发声 和 暂停声音
程序 调用
主控模块 (AT89C52)
时钟电路
发声模块
复位电路
按键模块
电源电路
于人耳,听觉系统将神经冲动传达给大脑,进而产生听觉。
人耳能听到的声音频率大约在 11—20000Hz,而音乐使用的音一般在 27—4100Hz。
乐音体系中各音级的名称叫做音名,被广泛采用的是 C D E F G A B (do re mi fa so la si 则多用于歌唱,称为唱名)。
乐音体系中音高关系的最小计量单位叫做半音,两个半音构成一个全音。
乐音中有几十个高低不同的音,但是最基本只有这七个音,其他高、低音名都是在这个基础上变化出来的。
乐谱表上用来表示正在进行的音的长短的符号,叫做音符。
不同的音符代表不同的长度。
音符有以下几种:全音符、二分音符、四分音符、八分音符、十六分音符、三十二分音符、六十四分音符。
此外,还有附点音符,它就是指带附点的音符,所谓附点就是记在音符右边的小圆点,表示增加前面音符时值的一半。
音持续的长短即时值,一般用拍数表示,休止符表示暂停发音。
一首音乐就是由许多不同的音符组成的,而每一个音符对应着不同的频率,这样就可以利用不同的频率的组合,加以拍数对应的延时来构成不同的音乐。
3.2音调脉冲和音乐节拍的实现
3.2.1 音调脉冲的产生
音调表示一个音符唱多高的频率,和平时所说的“音高”十分类似。
这是音乐学中的名词,在音乐中常把中央C上方的A音定为标准音高,其频率f=440Hz。
其余音均通过和其比较获得。
如果f1和f2两个音符的频率相差一倍时,也即f2=2×f1时,则称f2比
f1高一个倍频程。
音符1(低音do)与音符i(中音do),……,等之间正好相差一个倍频程,在音乐学中一般称其相差一个八度音。
音乐中规定,在一个八度音内,共有12个半音。
以1—八音区为例,这12个半音分别是:1—#1、#1—2、2—#2、#2—3、3—4、4—#4,#4—5、5—#5、#5—6、6—#6、#6—7、7—i。
由于人耳的听觉效果是非线性的,因此这12个音阶的分度基本上是以对数关系来划分的。
要让单片机产生音频脉冲,只要计算出某一音频的周期,将此周期除以2
得到半周期,利用定时器对此半周期进行定时,每当定时时间到,将P1.7口线
上的电平取反,从而得到所需要的音频脉冲。
产生音频的定时器初值计算公式如下:
式中,k根据单片机工作方式确定,可为13(方式0)、16(方式1)、8(方式2),
fosc为单片机工作频率,
为希望产生的音频。
例如中音DO的频率为523Hz,若单片机的工作频率为12MHz,定时器T0设置为工作方式1,按以上公式计算得定时器初值为64580;高音DO的频率为1047Hz,计算定时器初值为65058。
3.2.2音乐节拍的产生
节拍表示一个音符唱多长的时间,同样是音乐学中的名词。
在一张完整乐谱的开头,都有如1=C 、1=G …… 等的标识。
例如图3-2所示为1=C 的节拍示意图。
这里的、用来表示节拍,而1=C、1=G表示一个乐谱的曲调,简单地说就是跟音调有关系。
图3-2 节拍示意图
可以通过延时程序来产生不同的节拍。
如果1拍为0.4秒,则1/4为0.1秒,只要设定延时时间就可以求得节拍时间。
例如一段延时程序Delay为1/4拍,则一拍只要调用4次Delay程序,依此类推。
3.2.3音符码表的编制
编写一段音乐的音符码表时,先把乐谱的音符找出,按表3-1建立对应的音调码码及定时器初值表,按表3-2建立节拍码表。
每个音符使用1个字节,字节的高4位存放音符的音调码,低4位存放音符的节拍码。
表3-1 与音符对应的音调码表和定时器初值表(fosc=12MHz)
用C语言将音调码表和定时器初值表表示出来即为:
uchar code TABLE[ ]={ //音符对应的定时器初值表
0xfb,0x04,0xfb,0x90,0xfc,0x09,0xfc,0x44,
0xfc,0xac,0xfd,0x09,0xfd,0x34,0xfd,0x82,
0xfd,0xc8,0xfe,0x06,0xfe,0x22,0xfe,0x56,
0xfe,0x85,0xfe,0x9a,0xfe,0xc1};
表3-2节拍码表
按照上述原理可以编写出“Amazing Grace”乐曲的音符码表。
“Amazing Grace”的简谱如下:
5.|1-31 |3- 2| 1-
6. |5.- 5.|1-31|3-2|5--|5-|
3|5·353|1-5.| 6·116.|5.-5.|1-31|3-2|1--|1-|
对应的音符码表为:
uchar code GRACE[ ]={ //《奇异恩典》音符码表
0x14,0x48,0x62,0x42,0x68,0x54,0x48,0x24,0x18,
0x14,0x48,0x62,0x42,0x68,0x54,0x8c,0x88
0x64,0x86,0x62,0x82,0x62,0x48,0x14,0x26,0x42,0x42,0x22,0x18,
0x14,0x48,0x62,0x42,0x68,0x54,0x4c,0x48,0x00};
3.3主程序流程图
如图3-3所示为主程序流程图。
N
图3-3 主程序流程图
3.4发声模块程序设计
如图3-4所示为发声模块程序流程图。
图3-4 发声模块程序流程图
3.5按键模块程序设计
本设计中采用4个按键来控制音乐的播放:Key0 控制上一曲播放;Key1开始播放;Key2控制下一曲播放;Key3暂停播放。
主程序中放置了3首歌曲,分别是"Amazing Grace" ;"Ode To Joy" ;"Happy Birthday"。
进入主程序后,判断开始键是否按下,若按下,则按顺序循环播放这3首歌曲。
开始播放后,通过控制4个按键来控制歌曲的播放。
图3-5为按键模块程序流程图
N
图3-5 按键模块程序流程图
四、硬件电路设计
硬件电路主要由 AT89C52 单片机、三极管音频功放电路(图中为理想
原件,有三极管的音频放大可以增加声音效果)和蜂鸣器部分组成,电路结
构比较简单。
仿真图如下图所示:
4.1 主要器件
4.1.1 微处理器
AT89C52的功能全部兼容MCS-51,并且还有程序加密等功能,相对而言更加实用。
AT89C52单片机是美国ATMEL公司生产的低电压,高性能CMOS 8位微控制器,片内含8KB的可反复擦写的只读程序存储器和256字节的随机存取存储器,器件采用ATMEL公司的高密度、非易失性存储技术生产,与标准MCS-51指令系统及805日1产品引脚兼容,片内置通用8位中央处理器(CPU)和Flash存储单元,其强大的功能更适合较为复杂的控制应用场合。
其主要工作特性是:片内程序存储器内含8KB的Flash程序存储器,可擦写寿命为1000次;片内数据存储器内含256字节的RAM;具有32根可编程I/O口线;具有3个可编程定时器;中断系统是具有8个中断源、6个中断矢量、2级
优先权的结构;串行口是具有一个全双工的可编程串行通信口;具有一个数据指针DPTR;低功耗工作模式有空闲模式和掉电模式;具有可编程的3级程序锁定位;AT89C52工作电源电压为5(1±0.2)V,且典型值为5V;AT89C52最高工作频率为24MHZ。
下图为AT89C51单片机的实物图与引脚图:
图4-2 AT89C52单片机的实物图与引脚图
引脚功能描述如下:
P0口:—8位、漏极开路的双向I/O口。
当使用片外存储器及外扩I/O口时,P0口作为低字节地址/数据复用线。
在编程时,P0口可用于接收指令代码字节;在校验时,P0口可输出指令字节(须外加上拉电阻)。
P0口也可做通用I/O口使用,但需加上拉电阻,变为准双向口。
当作为普通输入时,应将输出锁存器置1。
P0口可驱动8个TTL负载。
P1口:—8位、准双向I/O口,具有内部上拉电阻。
P1口是为用户准备的I/O口双向口。
在编程和校验时,可用做输入低8位地址。
用做输入时,应先将输出锁存器置1。
P1口可驱动4个TTL负载。
P2口:—8位、准双向I/O口,具有内部上拉电阻。
当使用片外存储器或外扩I/O口时,P2口输出高8位地址。
在编程/校验时,P2口可接收高字节地址和
某些控制信号。
P2口也可做普通I/O口使用。
用做输入时,应先将输出锁存器置1。
P1口可驱动4个TTL负载。
P3口:—8位、准双向I/O口,具有内部上拉电阻。
P3口可做普通I/O口使用。
用作输入时,应先将输出锁存器置1。
在编程/校验时,P3口接收某些控制信号。
它可驱动4个TTL负载。
RST:复位输入。
晶振工作时,RST脚持续2个机器周期高电平将使单片机复位。
看门狗计时完成后,RST 脚输出 96 个晶振周期的高电平。
特殊寄存器AUXR(地址 8EH)上的 DISRTO位可以使此功能无效。
DISRTO默认状态下,复位高电平有效。
ALE/PROG:地址锁存控制信号(ALE)是访问外部程序存储器时,锁存低 8 位地址的输出脉冲。
在flash编程时,此引脚(PROG)也用作编程输入脉冲。
在一般情况下,ALE以晶振六分之一的固定频率输出脉冲,可用来作为外部定时器或时钟使用。
然而,特别强调,在每次访问外部数据存储器时,ALE脉冲将会跳过。
如果需要,通过将地址为8EH的SFR的第0位置“1”,ALE操作将无效。
这一位置“1”,ALE仅在执行MOVX或MOVC指令时有效。
否则,ALE 将被微弱拉高。
这个ALE使能标志位(地址为8EH的SFR的第0位)的设置对微控制器处于外部执行模式下无效。
PSEN:外部程序存储器选通信号(PSEN)是外部程序存储器选通信号。
当AT89S52从外部程序存储器执行外部代码时,PSEN在每个机器周期被激活两次,而在访问外部数据存储器时,PSEN将不被激活。
EA/VPP:访问外部程序存储器控制信号。
为使能从0000H到FFFFH的外部程序存储器读取指令,EA必须接GND。
为了执行内部程序指令,EA应该接 VCC。
在flash编程期间,EA也接收12伏VPP电压。
XTAL1:振荡器反相放大器和内部时钟发生电路的输入端。
XTAL2:振荡器反相放大器的输出端。
4.1.2开关元件
独立按键是51单片机应用系统中最常用的人机交互通道之一,它通常用于给用户提供向51单片机输入信息的通道。
独立按键的基本工作原理是:按键按下时接通两个点,放开时则断开这两个点。
按照结构可以把按键分为两类:触点式开关按键,如机械式开关、导电橡胶式开关等;无触点式开关按键,如电气式按键,磁感应按键等。
本设计的控制电路采用4个独立按键,如图4.1.2所示。
从左至右:Key0与P1.0口相连,播放上一曲;Key1与P1.1口相连,开始播放;Key2与P1.2口相连,播放下一曲;Key3与P1.3口相连,暂停播放。
当按键按下时,接口接收到低电平,从而实现对音乐器的控制。
图4.1.2 控制电路
4.2 发声驱动电路
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。
图2-4所示为蜂鸣器实物图。
图2-4 蜂鸣器实物图
蜂鸣器按其结构主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂
鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。
多谐振荡器由晶体管或集成电路构成。
当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。
压电蜂鸣片由锆钛酸铅或铌镁酸铅压电陶瓷材料制成。
在陶瓷片的两面镀上银电极,经极化和老化处理后,再与黄铜片或不锈钢片粘在一起。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。
振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
蜂鸣器按其是否带有信号源又分为有源和无源两种类型。
有源蜂鸣器只需要在其供电端加上额定直流电压,其内部的震荡器就可以产生固定频率的信号,驱动蜂鸣器发出声音。
无源蜂鸣器可以理解成与喇叭一样,需要在其供电端上加上高低不断变化的电信号才可以驱动发出声音。
用单片机控制蜂鸣器发出不同频率的声音,最好采用无源的蜂鸣器,如果用有源蜂鸣器,可以会因为二种不同频率声音(有源蜂鸣器本身固有发音频率与单片机驱动频率)互相叠加,造成效果混乱、发音不清。
4.3电路工作原理
当按下按键,P1.0口输出音乐脉冲,脉冲信号首先经过由电容C1和 C2
组成的回路输入到单片机XTAL1 XTAL2.输入信号经过晶振处后,从 Vout 输
出,送入到P0.0脚。
并且串联一个限流电阻R2,用以保护蜂鸣器的正常工
作。
经过此电路后,单片机发出的不同频率的音频信号就可以通过蜂鸣器发
出想要的歌曲。
五、软件设计
软件设计是指在硬件电路的基础上,以程序的形式实现算法,进而实现音乐播放器的功能。
软件是整个控制系统设计的核心,采用模块化设计,具有充分的灵活性,在硬件结构不变的情况下,只需要改变软件就能实现一些不同的功能,满足用户多样性需求。
本系统采用模块化的编程思想,把整个软件系统化分为多个功能模块,主程序通过调用各个子程序来完成各个功能的实现。
软件的程序主要由主程序、发声模块程序、控制模块程序、LCD1602显示程序组成。
本设计使用Keil μVison3软件完成程序的编写和调试。
5.1软件开发平台
Keil μVison系列是德国Keil Software公司推出的51系列兼容单片机软件开发系统。
μVison3是集成的可视化Windows操作界面,其提供了丰富的库函数和各种编译工具,能够对51系列单片机以及和51系列兼容的绝大部分类型的单片机进行设计。
Keil μVison系列可以支持单片机C51程序设计语言,也可以直接进行汇编语言的设计与编译。
目前,Keil公司已经被ARM公司收购,成为ARM旗下的产品。
Keil μV ison 系列的集成开发环境最高版本是μVison3,版本号为V8.08。
Keil μVison系列是一个非常优秀的编译器,受到广大单片机设计者的广泛使用。
其主要特点如有:支持汇编语言、C51语言等多种单片机设计语言;可视化的文件管理,界面友好;支持丰富的产品线,除了51及其兼容内核的单片机外,还新增加了对ARM内核产品的支持;具有完善的编译连接工具;具备丰富的仿真调试功能,可以仿真串口、并口、A/D、D/A、定时器/计数器以及中断等资源,同时也可以和外部仿真器联合进行在线调试;内嵌RTX-51实时多任务操作系统;支持在一个工作空间中进行多项目的程序设计。
支持多级代码优化。
5.2详细的程序设计
详细的程序设计如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SPEAK=P1^7; //定义蜂鸣器输出端口
sbit Key0=P1^0; //定义独立按键
sbit Key1=P1^1;
sbit Key2=P1^2;
sbit Key3=P1^3;
sbit RS=P2^0; //定义控制引脚
sbit RW=P2^1;
sbit E=P2^2;
uchar beat,tl,th; //定义节拍和T0初值变量
uchar code TABLE[]={ //音符对应的定时器初值表
0xfb,0x04,0xfb,0x90,0xfc,0x09,0xfc,0x44,
0xfc,0xac,0xfd,0x09,0xfd,0x34,0xfd,0x82,
0xfd,0xc8,0xfe,0x06,0xfe,0x22,0xfe,0x56,
0xfe,0x85,0xfe,0x9a,0xfe,0xc1};
uchar code GRACE[]={ //《奇异恩典》音符码表
0x14,0x48,0x62,0x42,0x68,0x54,0x48,0x24,0x18,
0x14,0x48,0x62,0x42,0x68,0x54,0x8c,0x88,
0x64,0x86,0x62,0x82,0x62,0x48,0x14,0x26,0x42,0x42,0x22,0x18,
0x14,0x48,0x62,0x42,0x68,0x54,0x4c,0x48,0x00};
uchar code JOY[]={ //《欢乐颂》音符码表
0x64,0x64,0x74,0x84,0x84,0x74,0x64,0x54,0x44,0x44,0x54,0x64,0x66, 0x52,0x58,
0x64,0x64,0x74,0x84,0x84,0x74,0x64,0x54,0x44,0x44,0x54,0x64,0x56, 0x42,0x48,
0x54,0x54,0x64,0x44,0x54,0x62,0x72,0x64,0x44,0x54,0x62,0x72,0x64, 0x54,0x44,0x54,0x18,
0x64,0x64,0x74,0x84,0x84,0x74,0x64,0x54,0x44,0x44,0x54,0x64,0x56, 0x42,0x48,0x00};
uchar code HAPPY[]={ //《生日快乐》音符码表
0x82,0x01,0x81,0x94,0x84,0xB4,0xA4,0x04,
0x82,0x01,0x81,0x94,0x84,0xC4,0xB4,0x04,
0x82,0x01,0x81,0xF4,0xD4,0xB4,0xA4,0x94,
0xE2,0x01,0xE1,0xD4,0xB4,0xC4,0xB4,0x04,
0x82,0x01,0x81,0x94,0x84,0xB4,0xA4,0x04,
0x82,0x01,0x81,0x94,0x84,0xC4,0xB4,0x04,
0x82,0x01,0x81,0xF4,0xD4,0xB4,0xA4,0x94,
0xE2,0x01,0xE1,0xD4,0xB4,0xC4,0xB4,0x04,
0x00};
uchar code GRACE_Name[]="Amazing Grace "; uchar code JOY_Name[]="Ode To Joy "; uchar code HAPPY_Name[]="Happy Birthday "; void Timer0_Initialize();
void Delay_1ms(uchar ms);
void Delay(uchar);
void Key_Scan(char *numz,uchar *kz);
uchar Busy_Check();
void LCD_Write_Command(uchar cmd);
void LCD_Initialize();
void Show_String(uchar x,uchar y,uchar *str);
void main()
{
uchar m,m1,k=0; //定义临时变量
char num=0;
char *numz;
uchar *kz;
uchar *p[3];
uchar *q[3];
numz=#
kz=&k;
p[0]=GRACE;p[1]=JOY;p[2]=HAPPY;
q[0]=GRACE_Name;q[1]=JOY_Name;q[2]=HAPPY_Name;
Timer0_Initialize();
LCD_Initialize();
while(Key1);
Delay_1ms(5);
while(Key1);
while(1)
{
while(*(p[num]+k)!=0) //判断取得的音符码是否为结束码
{
beat=*(p[num]+k)&0x0f; //取节拍码
m=_crol_(*(p[num]+k),4)&0x0f; //取音调码
if(m!=0) //判断取得的音调码是否为0
{ //不是,根据取得的音调码计算T0初值m1=--m*2+1;
m=m*2;
tl=TL0=TABLE[m1];
th=TH0=TABLE[m];
TR0=1; //启动T0
}
else //取得的音符码为0,则停止T0
TR0=0;
Delay(beat);
k++;
Show_String(0,0,q[num]);
Show_String(0,1,q[num]+16);
Key_Scan(numz,kz);
}
num++;
if(num>2)
num=0;
k=0;
}
}
/************************** T0初始化函数
****************************/
void Timer0_Initialize()
{
TMOD=0x01;
IE=0x82;
}
/************************* T0中断服务函数
***************************/
void timer0() interrupt 1 using 1
{
TL0=tl;TH0=th; //重装定时初值
SPEAK=~SPEAK; //蜂鸣器控制端口电平取反}
/************************ 四分之一拍延时函数
************************/
void Delay_Beat()
{
uint i;
for(i=0;i<20000;i++);
}
/************************** 节拍延时函数
****************************/
void Delay(uchar tt)
{
uchar i;
for(i=0;i<tt;i++)
Delay_Beat();
}
/***************************1ms延时函数****************************/
void Delay_1ms(uchar ms)
{
int i;
while(ms--)
for(i=125;i>0;i--);
}
/**************************按键扫描函数******************************/
void Key_Scan(char *numz,uchar *kz) {
bit flag;
if(!Key0)
{
Delay_1ms(5);
if(!Key0)
{
(*numz)--;
if(*numz<0)
*numz=2;
*kz=0;
}
}
else if(!Key2)
{
Delay_1ms(5);
if(!Key2)
{
(*numz)++;
if(*numz>2)
*numz=0;
*kz=0;
}
}
else if(!Key3)
{
Delay_1ms(5);
if(!Key3)
{
TR0=0;
flag=1;
while(flag)
{
if(!Key1)
{
Delay_1ms(5);
if(!Key1)
{
flag=0;
TR0=1;
}
}
}
}
}
while((!Key0)||(!Key1)||(!Key2));
}
/*******************检查1602是否处于忙状态函数
**********************/
uchar Busy_Check()
{
uchar LCD_Status;
RS=0;
RW=1;
E=1;
Delay_1ms(1); //为什么延时1ms呢?
LCD_Status=P0;
E=0;
return LCD_Status;
}
/************************向1602写入命令函数
*************************/
void LCD_Write_Command(uchar cmd)
{
while((Busy_Check()&0x80)==0x80); //如果1602忙 RS=0;
RW=0;
E=0;
P0=cmd;
E=1;
E=0;
}
/************************向1602写入数据函数
*************************/
void LCD_Write_Data(uchar dat)
{
while((Busy_Check()&0x80)==0x80);
RS=1;
RW=0;
E=0;
P0=dat;
E=1;
Delay_1ms(1);
E=0;
}
/*************************初始化1602液晶函数
************************/
void LCD_Initialize()
{
LCD_Write_Command(0x38); //设置1602液晶功能,8位数据接口,
//两行显示,5*10点阵字符
Delay_1ms(1);
LCD_Write_Command(0x01); //清屏
Delay_1ms(1);
LCD_Write_Command(0x06); //输入方式选择指令,数据读写后AC自动+1,
//输出显示保持不变
Delay_1ms(1);
LCD_Write_Command(0x0c); //开显示,关光标,关闪烁
}
/****************在坐标点X、Y上写入一个字符串函数*******************/ void Show_String(uchar x,uchar y,uchar *str)
{
uchar i=0;
if(y==0)
LCD_Write_Command(0x80|x);
if(y==1)
LCD_Write_Command(0xc0|x);
for(i=0;i<16;i++)
{
LCD_Write_Data(*(str+i));
}
}
总结
本设计阐述了基于单片机的蜂鸣器音乐器设计软硬件的实现过程,并完成了硬件仿真。
我非常喜欢我的毕业设计课题,因为我比较喜欢音乐,也学过一点的乐理知识,这在我编制乐谱的音符码表时,给了我很大的帮助。
而且我也非常喜欢单片机这门课,对单片机的硬件结构和工作原理由衷地喜欢,还有就是C语言程序设计也是我大学中学的比较好的一门课。
所以在做毕业设计之前是满心期待。
虽然完成硬件电路图的绘制只用了半天的时间,但是在编写软件的过程中,还是遇到了不少的问题。
很多时候是自己的粗心大意导致的,比如,C语言中的变量是先定义再使用,我是定义一个,使用一个,结果总是调试程序时出现错误,但是又找不到问题所在,因此在这上面花费了很多时间。
最后才知道是变量必须全部定义完,才能使用。
这个例子反映出,C语言基础还是不扎实,知识必须在实践中巩固和完善,而且在实践中才能掌握。
通过这次的毕业设计,不仅巩固了以前所学过的知识,而且学到了很多新的知识。
同时提高了自己的实际动手能力和独立思考的能力,在自己设计出的音乐器实现硬件仿真奏出简单音乐的时刻,真是满心欢喜,很有成就感,也增加了自己学习的兴趣。
当然本设计也有一些不足,例如,在播放下一首歌曲的瞬间,歌曲名字的会重复显示一次,这也是自己的程序设计能力的欠缺,有待提高。
总之,在这次的毕业设计中,收获很多,充实且快乐。
参考文献
[1] 于海生.计算机控制技术[M].北京:清华大学出版社,2007.
[2] 谭浩强.C程序设计.北京: 清华大学出版社,2005.
[3] 徐爱钧,徐阳. Keil C51 单片机高级语言应用编程与实践. 北京:电子工
业出版社, 2013.
[4] 万福君,等.单片微机原理系统设计与应用.合肥:中国科学技术大学出版
社,2001.
[5] 赵建领,崔昭霞.精通51单片机开发技术与应用实例[M].北京:电子工业
出版社,2012.
[6] 马忠梅.单片机的C语言应用程序设计[M].北京:北京航空航天大学出版社,
2003.
[7] 李玉梅.基于MCS-51系列单片机原理的应用设计[M].北京:国防工业出版
社,2006.
[8] 潘永雄.新编单片机原理与应用[M].西安:西安电子科技大学出版社,2003.
[9] 阎石.数字电子技术基础[M].北京:高等教育出版社,2006.
[10] 康华光.电子技术基础·模拟部分[M].北京:高等教育出版社,2006.
[11] 张鑫.单片机原理及应用[M].北京:电子工业出版社,2005.。