单片机课程设计含程序基于C51单片机的电子音乐盒Word文件下载.docx
《单片机课程设计含程序基于C51单片机的电子音乐盒Word文件下载.docx》由会员分享,可在线阅读,更多相关《单片机课程设计含程序基于C51单片机的电子音乐盒Word文件下载.docx(35页珍藏版)》请在冰豆网上搜索。
使用独立键盘通过软件来切换上下曲目,在4个曲子的情况下可以做到与4*4差不多的效率并且可以有效减小产品的大小提高便携度以及压缩成本。
2.2.1单片机选择
首先考虑到的是在课堂上所熟悉的ATMEL公司生产的AT89C51但是其后考虑到AT89C51内存仅为2K可能满足不了产品需求换成了性能更为优越的STC89C52单片机。
STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。
STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
第三章硬件设施
3.1单片机简介
3.2最小系统
最小系统中的电源供电模块的电源可以通过计算机的USB口供给也可使用外部稳定的5V电源供电模块供给。
电源电路中接入了电源开关并串入一个电阻R1,在单片机系统里晶振作用非常大,晶振X1结合单片机内部电路产生单片机所需的时钟频率,单片机晶振提供的时钟频率越高,那么单片机运行速度就越快,单片机的一切指令的执行都是建立在单片机晶振提供的时钟频率,图3-1为最小系统电路原理图。
图3-1最小系统原理图
3.3按键电路
本系统主要用到5个按键,其中一个用于系统手动复位,另外4个为独立式按键,该方法连接简单,一个按键接一个I/O口,程序处理比较简单,可节省CPU资源,按键连接电路如图3-2所示,4个独立按键分别于单片机P1.0、P1.1、P1.2、P1.3接口连接。
图3-2按键电路原理
4个按键功能说明:
P1.0——切断音乐播放器、暂停。
P1.1——播放下一首音乐
P1.2——播放上一首音乐
P1.3——预留按键(用于后期开发)
3.4LCD1602液晶显示电路
图3-3LCD1602液晶显示器实物图
用P2.0~P2.2作为LCD的RS、R/W、E的控制信号;
用P3.0~P3.7作为LCD的D0~D7的控制信号。
引脚说明:
1、VSS接电源地。
2、VDD接+5V。
3、VO是液晶显示的偏压信号,可接10K的3296精密电位器。
或同样阻值的RM065/RM063蓝白可调电阻。
4、RS是命令/数据选择引脚,接单片机的一个I/O,当RS为低电平时,选择命令;
当RS为高电平时,选择数据。
5、RW是读/写选择引脚,接单片机的一个I/O,当RW为低电平时,向LCD1602写入命令或数据;
当RW为高电平时,从LCD1602读取状态或数据。
如果不需要进行读取操作,可以直接将其接VSS。
6、E,执行命令的使能引脚,接单片机的一个I/O。
7、D0—D7,并行数据输入/输出引脚,可接单片机的P0—P3任意的8个I/O口。
如果接P0口,P0口应该接4.7K—10K的上拉电阻。
如果是4线并行驱动,只须接4个I/O口。
8、A背光正极,可接一个10—47欧的限流电阻到VDD。
9、K背光负极,接VSS。
1602指令说明:
1602液晶模块内部的控制器共有11条控制指令,如表3-1所示:
序号
指令
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
1
清显示
2
光标返回
*
3
置输入模式
I/D
S
4
显示开/关控制
D
C
B
5
光标或字符移位
S/C
R/L
6
置功能
DL
N
F
7
置字符发生存贮器地址
字符发生存贮器地址
8
置数据存贮器地址
显示数据存贮器地址
9
读忙标志或地址
BF
计数器地址
10
写数到CGRAM或DDRAM)
要写的数据内容
11
从CGRAM或DDRAM读数
读出的数据内容
表3-11602控制指令表
指令1:
清显示,指令码01H,光标复位到地址00H位置。
指令2:
光标复位,光标返回到地址00H。
指令3:
光标和显示模式设置I/D:
光标移动方向,高电平右移,低电平左移S:
屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效。
指令4:
显示开关控制。
D:
控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:
控制光标的开与关,高电平表示有光标,低电平表示无光标B:
控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:
光标或显示移位S/C:
高电平时移动显示的文字,低电平时移动光标。
指令6:
功能设置命令DL:
高电平时为4位总线,低电平时为8位总线N:
低电平时为单行显示,高电平时双行显示F:
低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
指令7:
字符发生器RAM地址设置。
指令8:
DDRAM地址设置。
指令9:
读忙信号和光标地址BF:
为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10、11:
写数据。
内部显示地址:
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。
要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图3-4是1602的内部显示地址。
图3-41602LCD内部显示地址
例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?
这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。
在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。
每次输入指令前都要判断液晶模块是否处于忙的状态。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如图3-4所示,这些字符有:
阿拉伯数字、英文字母的大小写、常用的符号等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”
3.5PCB图
图3-4产品PCB图
3.6发声模块(功率放大)
发声模块:
电动式纸盆扬声器结构心支片的作用是保证并在一定范围内限制纸盆只能沿轴向移动,它还起到防尘罩作用,防止尘埃进入磁路系统。
音圈、定心支片、纸盆等共同构成了扬声器的发音振动系统。
扬声器的另一系统是磁路系统。
它包括磁体和导磁系统。
盆架、压边等是扬声器的辅助系统。
当通电的导线(或线圈)放入磁场中时,导线就会受到一个与磁力线垂直方向的力,其方向符合左手定则,故音圈是向上运动的。
当磁场磁通密度为B(特[斯拉]),音圈导线长度为/(m),导线流过的电流为/(A)时,导线受力F为F—B.Z.i(N)。
显然当在扬声器音圈中通入一个音频电流信号时,音圈就会受到一个大小与音频电流成正比、方向随音频电流变化而变化的力,从而产生音频振动,带动纸盆振动,迫使周围空气发出声波。
放大模块:
由于使用5V电压输入,直接给扬声器供电电压低,发声低,我们采用三极管的放大原理,采用9013型NPN型三级管功率放大,增大扬声器声音。
图3-5放大模块
第四章软件设计
4.1软件模块及发声原理
该系统由延时165MS,即十六分音符子函数、延时1MS子函数、按键扫描子函数、播放音乐子函数、定时器0中断子函数、显示函数、显示延时函数、选择播放函数、主函数和数据定义这几部分组成。
发声模块的设计。
先将音调与节拍分别放入两个数组中进行保存,编曲时讲对应的值根据简谱写入一个存放歌曲的数组,从数组中取出一个数,播放时从中读取相应的音调与节拍值赋给定时器0使之发出音调,再用延时程序决定节拍,时发声部件发生。
4.1.1音调的产生
频率的高低决定了音调的高低。
音乐的十二平均率规定:
每两个八度音(如简谱中的中音1和高音1)之间的频率相差一倍。
在两个八度音之间又分为十二个半音。
另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间、E到F之间为半音,其余为全音。
由此可以计算出简谱中从低音1到高音1之间每个音名对应的频率,所有不同频率的信号都是从同一个基准频率分频得到的。
1、要产生音频脉冲,只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。
利用定时器计时这半个周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率的脉冲。
2、利用AT89C51的内部定时器使其工作在计数器模式MODE1下,改变计数值TH0及TL0以产生不同频率的方法。
此外结束符和休止符可以分别用代码00H和FFH来表示,若查表结果为00H,则表示曲子终了;
若查表结果为FFH,则产生相应的停顿效果。
3、例如频率为523Hz,其周期T=1/523=1912us,因此只要令计数器计时956us/1us=956,在每次技术956次时将I/O反相,就可得到中音DO(523Hz)。
计数脉冲值与频率的关系公式如下:
N=Fi
Fr
N:
计算值;
Fi:
内部计时一次为1us,故其频率为1MHz;
4、其计数值的求法如下:
初值T=65536-N=65536-Fi
Fr
例如:
设K=65536,F=1000000=Fi=1MHz,球低音DO(261Hz)。
中音DO(523Hz)。
高音的DO(1046Hz)的计算值
T=65536-N=65536-Fi
Fr=65536-1000000
Fr=65536-500000/Fr
低音DO的T=65536-500000/262=63627
低音DO的T=65536-500000/523=64580
低音DO的T=65536-500000/1047=65059
C调各音符频率与计数值T的对照表如表4-1所示。
低音
频率
参数
中音
高音
Do
262
1908
229
523
956
115
1046
57
Do#
277
1805
217
Do﹟
554
903
108
1109
54
Re3
294
1701
204
Re
587
852
102
1175
51
Re﹟
311
1608
193
622
804
97
1245
48
Mi
330
1515
182
659
759
91
1318
45
Fa
349
1433
172
698
716
86
1397
43
Fa﹟
370
1351
162
740
676
81
1480
41
So
392
1276
153
784
638
77
1568
38
So﹟
415
1205
145
831
602
72
1661
36
La
440
1136
136
880
568
68
1760
34
La﹟
464
1078
129
932
536
64
1865
32
Si
494
1012
121
988
506
61
1976
30
图4-1C调各音符频率与计数值T的对照表
4.1.2节拍的确定
若要构成音乐,光有音调是不够的,还需要节拍,让音乐具有旋律(固定的律动),而且可以调节各个音的快满度。
“节拍”,即Beat,简单说就是打拍子,就像我们听音乐不自主的随之拍手或跺脚。
若1拍实0.5s,则1/4拍为0.125s。
至于1拍多少s,并没有严格规定,就像人的心跳一样,大部分人的心跳是每分钟72下,有些人快一点,有些人慢一点,只要听的悦耳就好。
音持续时间的长短即时值,一般用拍数表示。
休止符表示暂停发音。
一首音乐是由许多不同的音符组成的,而每个音符对应着不同频率,这样就可以利用不同的频率的组合,加以与拍数对应的延时,构成音乐。
了解音乐的一些基础知识,我们可知产生不同频率的音频脉冲即能产生音乐。
对于单片机来说,产生不同频率的脉冲是非常方便的,利用单片机的定时/计数器来产生这样的方波频率信号。
因此,需要弄清楚音乐中的音符和对应的频率,以及单片机定时计数的关系。
节拍码
节拍数
1/4拍
1/8拍
2/4拍
3/4拍
3/8拍
1拍
2/1拍
1又1/4拍
5/8拍
1又1/2拍
2拍
A
2又1/2拍
3拍
3又3/4拍
图4-2节拍与节拍码对照
每个音符使用1个字节,字节的高4位代表音符的高低,低4位代表音符的节拍,表2.41为节拍码的对照。
如果1拍为0.4秒,1/4拍实0.1秒,只要设定延迟时间就可求得节拍的时间。
假设1/4拍为1DELAY,则1拍应为4DELAY,以此类推。
所以只要求得1/4拍的DELAY时间,其余的节拍就是它的倍数,如图4-3为1/4和1/8节拍的时间设定。
曲调值
DELAY
调4/4
125毫秒
62毫秒
调3/4
187毫秒
94毫秒
调2/4
250毫秒
图4-31/4和1/8节拍的时间设定
4.2软件设计流程
4.3发声程序:
voidt0int()interrupt1//T0中断程序,控制发音音调
{
ucharg;
g=pm;
TR0=0;
//关闭T0
speaker=~speaker;
//输出方波,发音
keysm();
if(pm!
=g)
{
led=~led;
x_flag=0xff;
}
TH0=t0h;
//下次中断时间,这个时间控制音量高低
TL0=t0l;
TR0=1;
//启动T0
}
//--------------------------------------
voiddelay(uchart)//延时程序,控制音量发音长度120ms(1/4拍)
uchara,b,c;
while(t--)//四重循环,共延时t个1/4拍
{
for(c=193;
c>
0;
c--)
for(b=114;
b>
b--)
for(a=1;
a>
a--);
}
//延时期间,可进入T0中断去发音
//关闭T0停止发音
4.4按键电路设计
voidkeysm()
if(k1==0)
{
delay2(100);
Write_Str(1,1,"
WELCOME_YOU"
);
Write_Str(6,2,"
shuzi_yinyue_he"
while
(1)
{EA=0;
if(k1==0)
{
EA=1;
break;
}
if(k2==0)
delay2(50);
{if(k2==0)
pm++;
if(pm>
4)
pm=1;
}
if(k3==0)
if(k3==0)
{pm--;
if(pm<
1)
pm=4;
4.5LCD1602液晶显示电路设计
4.5.1LCD显示模块
#include"
lcd_1602.h"
delay.h"
voidcheck_busy(void)
unsignedcharbusy;
do
Lcd1602_E=0;
Lcd1602_RS=0;
Lcd1602_RW=1;
Lcd1602_E=1;
busy=LCD_PORT;
while(busy&
0x80);
Lcd1602_E=0;
voidControl_Lcd1602(charRS,charRW,charport_data)
check_busy();
Lcd1602_RS=RS;
Lcd1602_RW=RW;
LCD_PORT=port_data;
Lcd1602_E=1;
voidLcd1602_Init(void)
Control_Lcd16