详细代码讨论加我QQ:1271370903
一、设计题目、内容及要求
1.题目:基于单片机的电子贺卡设计
2.内容:
1、设计基于单片机的伴奏乐曲
2、设计基于单片机的彩屏图片
3、通过矩阵键盘按键显示不同彩屏图片,并伴有不同乐曲
4、创新部分(自主设计)
3.要求:
1、根据设计内容,设计系统硬件结构,画出系统流程图。
2、应用Keil、Proteus软件开发应用系统并仿真调试。
二、需求分析
目前市场上有很多种音乐芯片或音乐模块,可以直接产生各种曲子。但是这种模块价格比较贵,性价比不高。对于一些仅需要产生简单的音符或简短曲子的场合,例如智能玩具、电子贺卡等,可以使用单片机配合简单的蜂鸣器就能产生需要的音乐效果,这种方法充分发挥了单片机的优势。单片机渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。因此,单片机的学习、开发与应用将造就一批计算机应用与智能化控制的科学家、工程师。利用单片机实现音乐播放有很多要点,例如外部电路简单,控制方便等,因而备受广大单片机爱好者的喜爱。通过音乐发声器的设计方案,掌握C语言的编程方法。并熟练的运用AT89C52单片机定时器产生固定频率的方波信号,推动喇叭发出旋律,按下单键可以演奏预先设置的歌曲旋律,最重要的是自己还可以通过程序设计输入自己喜欢的歌曲来演奏。
三、系统硬件设计
3.1 硬件仿真图
单片机为核心元件,P1口低四位作为矩阵键盘的控制引脚,通过按键控制进行相应曲目切换与停止。单片机内部的定时器/计数器使P2.7输出一系列不同频率的脉冲控制音调的变化,蜂鸣器连接P2.7实现发声。P3口连接AMPIRE12864的数据输入输出引脚。每当进行曲目切换时便执行相应显示函数使屏幕显示图片。如图3.1,
3.2 键盘控制
本设计采用22矩阵键盘控制相应曲目播放,每个按键进行实时扫描以检测是否有按键按下。三个按键控制曲目切换,一个按键控制停止曲目播放。如图3.2,
3.3 发声装置
通过单片机定时器/计数器使P2.7输出一系列不同频率的脉冲控制音调高低与延时函数控制节拍,使用蜂鸣器放出乐曲。如图3.3,
3.4 显示装置
通过AMPIRE128*64显示对应曲目图片,液晶模块显示汉字方法:使用图形液晶模块以点阵形式来显示汉字和图形,每8个点组成1个字节,每个点用一个二进制位表示,存1的点显示时在屏上显示一个亮点,存0的点则在屏上不显示,在液晶屏上竖向8个点为1个字节数据,通过字模提取软件按照先左后右,先上后下倒序的方式对汉字进行字模提取。如图3.4,
.四、主要程序设计
4.1 程序设计思想
4.1.1 音调脉冲的产生
要让单片机产生音频脉冲,只要计算出某一音频的周期,将此周期除以2得到半周期,利用定时器对此半周期进行定时,每当定时时间到时,就将P2.7引脚上的电平取反,从而得到所需要的音频脉冲。
4.1.2音乐节拍的产生
可以通过延时程序来产生不同的节拍。如果1拍为0.4秒,则1/4为0.1秒,只要设定延时时间就可以求得节拍时间。例如一段延时程序Delay为1/4拍,则一拍只要调用4次Delay程序,依此类推。
4.1.3 音符码表的编制
编写一段音乐音符码表时,先把乐谱的音符找出,建立对应的音调码及定时器初值表,建立节拍码表。每个音符使用1个字节,字节的高4位存放音符的音调码,低4位存放音符的节拍码。音符对应的音调码表和定时器初值表(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};音符码表为: uchar code GRACE[ ]={ //《奇异恩典》音符码表
0x14,0x48,0x62,0x42,0x68,0x54,0x48,0x24,0x18,0x14,0x48,0x62,0x42,0x68,0x54,0x8c,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};
本程序使用2*2矩阵键盘,通过P1.0,P1.1控制键盘列,P1.2,P1.3控制键盘列。相关程序如下:
void Key_Scan() { uchar i,temp1; P1=0xfb;for(i=0;i<=1;i++){if(L1==0){if(i==0)key=a[i];elsekey=a[i+1];}if(L2==0){ if(i==0)key=a[i+1];else key=a[i+2];}delay_10ms();temp1=P1;temp1=temp1|0x03;temp1=temp1<<1;temp1=temp1|0x03;P1=temp1;}}
- 利用全局变量key来获取按下的键号,并使用key值充当switch-case循环语句参数执行相应的播放程序。每次调用相应的音调码后便执行键盘扫描函数,如有按键按下,则进行曲目切换。播放整首曲目部分程序如下:
while(*(p[key]+k)!=0) //判断取得的音符码是否为结束码 { beat=*(p[key]+k)&0x0f; //取节拍码 m=_crol_(*(p[key]+k),4)&0x0f; //取音调码 if(beat!=0){ //判断取得的音调码是否为0, 若不是,根据取得的音调码计算T0初值 m1=--m*2+1; m=m*2; tl=TL0=TABLE[m1]; th=TH0=TABLE[m]; } else{ //取得的节拍码为0,则停止T0 TR0=0;} Delay(beat); k++;Key_Scan();delay_10ms();if(temp!=key)break; }TR0=0;k=0;break;
4.2 主程序框图