北邮单片机实验报告简易电子琴.docx
《北邮单片机实验报告简易电子琴.docx》由会员分享,可在线阅读,更多相关《北邮单片机实验报告简易电子琴.docx(58页珍藏版)》请在冰豆网上搜索。
北邮单片机实验报告简易电子琴
2014年小学期单片机设计实验报告
题目:
基于单片机的电子音乐发生器
班级:
班内序号:
实验组号:
学生姓名:
指导教师:
基于单片机的电子音乐发生器
实验摘要
此次本组制作的基于PIC单片机的电子音乐发生器是具有LCD显示屏提示的音乐简单演奏、播放、存储等功能的演示作品,拥有以下4种功能:
1.按键演奏:
即“电子琴”功能,可以用键盘上的“1”到“A”键演奏从低音sol到高音do等11个音;
2.点歌功能:
即按动“B”“C”键分别演奏两首乐曲(可以表现准确的音高和音长)。
3.存储音乐功能:
即按右下角“F存储”键,然后按键演奏并存储,随后按“E”键结束,之后按“D键”就可以播放存储的乐曲了;
4.液晶显示功能:
即在开始时显示“hello!
”,在点播时分别显示“songb”、“songc”,在存储时显示“saving”。
电子音乐发生器采用以Microchip公司的PIC16F877芯片为核心的简单控制系统,外部电路连接有喇叭、键盘、LCD液晶显示屏以及其他必要系统调节元件。
软件设计中涉及PORTB\PORTC\PORTD\PORTE用作普通数字I/O脚功能。
本实验用单片机PORTB\D接收来自键盘输入的指令信息,由此确定LCD液晶屏幕显示以及喇叭播放内容,再通过PORTC\D\E输出声音或字幕信息。
关键字
单片机——microcontroller芯片——CMOSchip
音乐发生器——musicgenerator分频——fractionalfrequency
一、实验论证与比较
本设计的核心器件是单片机芯片和音频功放芯片。
单片机采用以Microchip公司的PIC16F87X系列中的PIC16F877芯片为核心构建简单控制系统,它完全可以满足本设计功能的需要。
此音乐发生器设计利用单片机的输入输出功能,当按下播放功能键时,单片机的输出功能使外部电路连接的喇叭和LCD液晶显示屏同时播放声音及显示文字,从而实现各种复杂音乐播放器的功能。
在嵌入式系统设计中,扬声器等是常用的输出设备,它具有使用方便、价格便宜、电路接口简单等优点,因此,在嵌入式系统中被广泛使用。
同时随着单片机的发展,其功能越来越强大,技术也越来越成熟,由此生产的音乐播放器越来越受到人们的喜爱。
因此,在技术性操作、社会因素和经济方面都具有良好的可行性。
我在实验中负责了全部软件设计,代码的编写,电路图的设计,以及部分硬件焊接。
其中,困难的部分在于,理论上认为电子音乐发生器模拟真正乐器的仿真实现方法,与现实电路实现起来有着一定的差别,在长音、乐谱存储播放上,以及存储功能的代码编写都有一定的难度。
二、系统总体设计
1、系统模块总体框图
2、系统整体流程图
3、发音原理
播放一段音乐需要的是两个元素,一个是音调,另一个是音符。
首先要了解对应的音调,音调主要由声音的频率决定,同时也与声音强度有关。
对一定强度的纯音,音调随频率的升降而升降;对一定频率的纯音、低频纯音的音调随声强增加而下降,高频纯音的音调却随强度增加而上升。
另外,音符的频率有所不同。
基于上面的内容,这样就对发音的原理有了一些初步的了解。
将相应音高的分频值存储在寄存器里,并将其与对应的按键进行关联,通过键盘扫描子程序将对应的分频值送入单音播放子程序即可产生相应频率的电压方波,再将其输出到喇叭即可产生对应的音高实现电子琴功能。
将音符按音高和音长直接存储在数据存储器里并与按键相关联,调用自动演奏子程序产生相应频率和时长的方波电压输出到喇叭即可。
三、硬件连接
1、键盘和单片机的连接
选择用4*4行列式键盘完成输入。
4*4行列式键盘又称为矩阵键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。
在行线和列线的每一个交叉点上,设置一个按键。
这样键盘中按键的个数是4×4个。
这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。
引脚号
所连接的单片机的管脚
引脚号
所连接的单片机的管脚
1
RD4
5
RB0
2
RD5
6
RB1
3
RD6
7
RB2
4
RD7
8
RB3
2、LCD和单片机的连接
采用型号为RT1602C的液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字、图形,显示多样,清晰可见,与传统的阴极射线管相比,液晶显示屏具有占用空间小、低功耗、低辐射、无闪烁、降低视觉疲劳等优点。
字符型液晶屏是一种用5*7点阵图形来显示字符的液晶显示器,根据显示的容量可以分为1行16个字、2行16个字、2行20个字等,最常用的为2行16个字。
型号为RT1602C的液晶显示屏就是2行16个字。
它有16个管脚,分别有电源地、电源正、偏压信号、读写控制、使能控制、I/O接口、背光控制等功能。
它的读写操作、屏幕和光标的操作都是通过指令编程来实现的。
脚号
符号
管脚功能及接发
脚号
符号
管脚功能及接发
1
VSS
电源地
9
DB2
数据I/ORD2
2
VDD
电源正
10
DB3
数据I/ORD3
3
VO
对比调整电压
11
DB4
数据I/ORD4
4
RS
数据/命令控制RE0
12
DB5
数据I/ORD5
5
R/W
读/写控制
13
DB6
数据I/ORD6
6
E
使能信号RE1
14
DB7
数据I/ORD7
7
DBO
数据I/ORD0
15
BLA
背光源正
8
DBI
数据I/ORD1
16
BLK
背光源负
3、扬声器和单片机的连接
扬声器的连接方法较前面的容易很多。
起初是将喇叭的正极直接连接在RE0上,负极接地,但我们发现这样发出的声音很小,音色也不好,于是在喇叭和单片机之间增加了一E个功率放大模块,这样声音就放大、稳定了很多。
四、调试过程
1、软件程序部分
我们首先在大体上对音乐播放器的功能按几个部分进行了划分,其中包括键盘扫描、单键演奏、键盘点播乐曲、音乐输入存储及播放、液晶显示等几个部分。
1)、音乐的存储和演奏:
起初我们设想把音乐的声调高低这些信息用不同的电压代表。
通过A\D转换存储到内存单元里,而这不同的电压正可以通过不同的按键实现,后来在具体编程时发现有困难,于是在网上查到相应音高的分频值存储在寄存器里,并将其与对应的按键进行关联,通过键盘扫描子程序将对应的分频值送入单音播放子程序即可产生相应频率的电压方波,再将其输出到喇叭即可产生对应的音高实现电子琴功能。
将音符按音高和音长直接存储在数据存储器里并与按键相关联,调用自动演奏子程序产生相应频率和时长的方波电压输出到喇叭即可。
2)、液晶显示:
应用了查表功能按四位16进制显示在液晶屏上。
3)、键盘扫描:
键盘扫描子程序是根据实验板的布线,先让行输出高电平,列为低电平,如有键按下则此键所在行也变成低电平,由此取得行码;同理取得列码,将两个码首尾相接取得键位码,并且事先将据此设计好的键位码存在寄存器里,通过地址指针不断将取得的键位码与预置的键位码比较从而确定出哪个键被按下了。
4)、音乐存储及播放部分:
用F键将标志位置1后进入存储状态,将按下的键逐一存到一串连续的地址中去,可是fsr指针只有一个,键盘扫描时用到了,所以在存储时只好在每次存储前重新对fsr赋值。
自动播放子程序因为知道了音长是按几分音符来控制的,而且都是倍数关系,于是我又加了一个计数器用来控制音长。
(1)存储功能流程图
(2)单音独奏功能流程图
(3)重放功能流程图
2、硬件部分
硬件部分的完成分为:
电路图的设计、实验板的焊接、实际电路的整体连接三部分。
在实验开始前的开题报告中,我组还准备加入蓝牙模块,可以通过手机控制音乐的播放。
因为知道PIC16F877单片机有USART端口(RC6,RC7),可以进行串行通信,只需借助有USART端口的蓝牙模块,就可以通过蓝牙模块来与蓝牙设备进行通信,这样就可以手机来控制单片机来产生调用相应的程序来产生一定频率的声音,并且PIC16F877的串行通信模块,在接收缓冲寄存器满时,在中断使能的情况下可以产生中断,这样就可以跳入中断子程序,从而就能够实时控制单片机,来实时弹奏音乐。
所以蓝牙电子琴是可行的。
在前面的过程基本完成并测试稳定后,我们开始了对蓝牙模块的研究,研究过程并不顺利,首先在器材上我们的购买的蓝牙芯片只有连接凹槽,没有连接管脚,这一时让我们犯了难。
后来通过向老师求助,拿到了一个可以引出插孔的小电路板,但是焊接有一些困难。
原本老师想要帮助我们,我们最后还是决定自己完成,通过多次练习和谨慎的焊接之后,我们终于成功的自己焊接上了。
后面面临的困难却没有这么容易克服了,不但编程烧入后LED灯的点亮情况一直不正确,也不能用手机搜索到该蓝牙设备,在反复调试失败和验收时间迫近的情况下,我们不得不选择放弃使用蓝牙模块。
这是我们这次实验的一个遗憾。
五、参考文献
PIC单片机实用教程——基础篇(五号宋体)
李学海
北京航空航天大学出版社
使用说明:
的确是一本不可或缺的教材,本书列举了很多实用的具有实战意义的例子,单片机入门就是通过把这本书里的好例子一字一行敲进电脑去来实现的。
PIC单片机实用教程——提高篇
李学海
北京航空航天大学出版社
使用说明:
继承了前面基础篇的风格,例子也具有实战意义,主要讲RA、TMR2的使用和CCP模块的PWM脉宽调制功能。
六、实验心得体会
小学期的第一周基本上是泡在实验室,一日三餐基本上是在实验室解决的。
在这一周里,一直在看书,也就是在这一周里看了快两本有关PIC单片机相关的资料书。
感觉相当的充实,同时也学到了很多东西,几乎是从零开始,一点点地学习汇编语言,一点点地学学PIC16F877的知识,到现在每一个管脚都还在脑海中。
硬件也是自己动手,从电路的设计到电路的焊接。
现在来看这个小学期学到了许多东西。
刚开始是感觉挺难的,通过耐心的学习,我从不甚了解到编出自己的程序,到调试成功,真的是学到了很多。
开始时心里一点底也没有,直到键盘扫描和单键演奏程序编出来后才逐渐有了信心,当我们按下键盘喇叭第一次发出音阶时,我真是激动极了,那种成就感真的是难以言表。
虽然实验过程中遇到很多困难比如自动播放子程序开始编的程序在演奏时只表现音高而没有表现音长,所以放出来的乐曲效果很差,还有存储代码想了好久,但是我都通过自己思考以及查阅资料或询问老师将问题解决了,我不仅了解到了自学的乐趣和重要性,同时也锻炼了实验中的动手能力,了解了汇编语言,更重要的是这次合作式的小学期也让我体会出团队的团结、相互的默契和彼此的信任在团队(尽管这个团队也许只有两三个人)的协作中是多么重要,同时也为我们步入社会、参加工作提供了一次很好的“演练”机会。
虽然已经完成了本次小学期的任务,但最后的结果相较于最初的预期还是有一定的差距,这是自身能力尚且不足的体现。
其实在学校要学的不仅是书本上的东西,更重要的是自学的能力、独立思考的能力和动手的能力。
要想在竞争异常激烈的现代社会立足,就必须有实力。
在学校的时间是最好的学习机会,一定要珍惜好这有限的时间,多学知识,尽量充实自己,为以后进入社会多做准备。
附代码:
;****************************变量定义区***********************************
indfequ00h
tmr0equ01h
pclequ02h
statusequ03h
cequ0
zequ2
rp0equ5
rp1equ6
fsrequ04h
fsr2equ05h
portbequ06h
trisbequ86h
portcequ07h
triscequ87h
portdequ08h
trisdequ88h
porteequ09h
triseequ89h
pclathequ0ah
intconequ0bh
t0ifequ2
t0ieequ5
pir1equ0ch;定义第一中断标志寄存器
pie1equ8ch;定义第一中断使能寄存器
tmr1lequ0eh;定义定时器1低位寄存器地址
tmr1hequ0fh;定义定时器1高位寄存器地址
t1conequ10h;定义tmr1控制寄存器
rcstaequ18h
txstaequ98h
txregequ19h
spbrgequ99h
rcregequ1ah
gieequ7
peieequ6
rcifequ5
rcieequ5
txifequ4
option_regequ81h
rbpuequ7
delMequ20h;定义两个延时变量寄存器
delNequ21h
delKequ0ffh;定义一个内层循环延时常数
valueequ22h;暂存按键列码和位置码
w_tempequ23h;定义备份w的地址
countequ24h;定义循环次数寄存器地址
portc_pequ25h;定义缓冲端口c的数据寄存器地址
rdelayequ26h;定义音乐延时寄存器地址
flag1equ27h;定义复选标志寄存器的地址
flag2equ28h;定义二次复选寄存器的地址
count2equ29h
indf2equ2ah
tmp1equ2fh;定义临时寄存器地址
tmr1lbequ30h
tmr1hbequ31h
adcon1equ9fh
doequ50h;定义音符
reequ51h
miequ52h
faequ53h
solequ54h
laequ55h
siequ56h
Hdoequ57h
Lsolequ58h
Llaequ59h
Lsiequ5ah
Hreequ5bh
Hmiequ5ch
Hfaequ5dh
p1lequ60h;定义拍节寄存器地址
p1hequ61h
p2lequ62h
p2hequ63h
p3lequ64h
p3hequ65h
p4lequ66h
p4hequ67h
p05lequ68h
p05hequ69h
p15lequ6ah
p15hequ6bh
p025lequ6ch
p025hequ6dh
p075lequ6eh
p075hequ6fh
;********************数据寄存器写入welcome****************************
reset
org0000h
nop
calllcdinit
movlw77h;w
bsfporte,0
calllcdsend
movlw65h;e
calllcdsend
movlw6ch;l
calllcdsend
movlw63h;c
calllcdsend
movlw6fh;o
calllcdsend
movlw6dh;m
calllcdsend
movlw65h;e
calllcdsend
movlwb'10100000'
calllcdsend
movlwb'01110100'
calllcdsend
movlwb'01101111'
calllcdsend
movlwb'10100000'
calllcdsend
movlwb'01110101';use
calllcdsend
movlwb'01110011'
calllcdsend
movlwb'01100101'
calllcdsend
bcfporte,0;nextrow
movlwb'11000000'
calllcdsend
movlwb'00000001'
movwfporte
movlwb’01000010’
calllcdsend
movlwb'01000011'
calllcdsend
movlwb'00111010'
calllcdsend
movlw53h;s
bsfporte,0
calllcdsend
movlw4fh;o
calllcdsend
movlw4eh;n
calllcdsend
movlw47h;g
calllcdsend
movlwb’01000110’
calllcdsend
movlw73h;s
bsfporte,0
calllcdsend
movlw61h;a
calllcdsend
movlw76h;v
calllcdsend
movlw65h;e
calllcdsend
;*****************************主程序****************************
main
bsfstatus,5;设置文件寄存器的体1
movlw00h;将端口c的方向控制码00h先送w
movwftrisc;再转到方向寄存器,将其设为输出
movlw07h
movwfadcon1
movlw00h
movwftrise
movlw0ffh;同理,将端口b设置为输入
movwftrisb;
movlw0ffh;将端口d设置为输入
movwftrisd;
bsfpie1,0;开放tmr1中断使能位
bcfstatus,5;恢复文件寄存器的体0
movlw34h;设置控制寄存器内容:
暂时不打开tmr1
movwft1con;预分频器设为“1:
8“
clrfportc
gotohz
;******************************音高分频值对应表***************************
hzmovlwd'100'
movwfdo
movlwd'117'
movwfre
movlwd'132'
movwfmi
movlwd'139'
movwffa
movlwd'152'
movwfsol
movlwd'163'
movwfla
movlwd'173'
movwfsi
movlwd'178'
movwfHdo
movlwd'48'
movwfLsol
movlwd'70'
movwfLla
movlwd'91'
movwfLsi
;*****************************音符延时对应表****************************
movlw85h;1p分频初始值
movwfp1h
movlw0eeh
movwfp1l
movlw00bh
movwfp2h
movlw0dch
movwfp2l
movlw0c2h
movwfp05h
movlw0f7h
movwfp05l
movlw48h
movwfp15h
movlw0e5h
movwfp15l
movlw0e1h
movwfp025h
movlw7bh
movwfp025l
movlw0a4h
movwfp075h
movlw72h
movwfp075l
;**************************在ram中建立键位码表*************************
movlw77h;1
movwf40h;
movlw7bh;2
movwf41h;
movlw7dh;3
movwf42h;
movlw7eh;4
movwf43h;
movlw0b7h;5
movwf44h;
movlw0bbh;6
movwf45h;
movlw0bdh;7
movwf46h;
movlw0beh;8
movwf47h;
movlw0d7h;9
movwf48h;
movlw0dbh;0
movwf49h;
movlw0ddh;a
movwf4ah;
movlw0deh;b
movwf4bh;
movlw0e7h;c
movwf4ch;
movlw0ebh;d
movwf4dh;
movlw0edh;e
movwf4eh;
movlw0eeh;f
movwf4fh;
check
bcfflag2,0
callkbscan;调用键盘扫描子程序
comfvalue,0;位置码取反送w
btfscstatus,2;测试有键按否?
有!
跳过下条指令
gotocheck;无!
则循环检测
movlw.13;预置外循环变量
movwfdelM;以便产生10ms延时
calldelay;调用延时子程序消除抖动
callkbscan;再次调用键盘扫描子程序
btfscstatus,2;测试有键按否?
有!
跳过下条指令
gotocheck;无!
则循环检测
gototrans;调用键值翻译子程序
gotocheck
;**************************键盘扫描和按键识别子程序*************************
kbscan
bsfstatus,5;设置文件寄存器的体1
bcfstatus,6;
bcf