实验十单片机演奏乐曲实验 (1)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告十
一、实验目的
1.、进一步掌握51单片机定时计数器、中断以及通过I/O口的综合应用
2.、熟练掌握有多种中断源应用系统程序的编写和调试方法
二、实验内容
1、编程实现通过键盘选择演奏曲目,驱动实验板上的喇叭,完成乐曲的演奏。
2、完成该任务要求用两个定时器,一个负责控制发出音符对应频率信号,另一个负责控制每个音的持续时间(节拍),同时,要求外部中断接受用户用按键对乐曲选择,用一位数码管显示正在演奏的乐曲代号。程序要求设计成能重复选择。
C调常用音频及其对应频率如下表:
音符频率T值音符频率T值
7
SI 494 64603 5 So 784 64948
1 DO 523 64654 6 La 880 65012
2 Re 587 64751 7 Si 987 65069
3 Mi 659 64837 1 DO 1046 65095
4 Fa 698 6487
5 2 RE 1174 65143
三、实验相关说明
1
、实验电路原理图
开始
中断初始化,TR0=0,TR1=0
T1装50ms初值
数码管显示歌曲代码,不选择则显示0
Si按下?
分离出第i首歌的音符跟音长
T0装第i首歌音符初值
TR0=1,TR1=1
结束
外部中断1流程图: T0中断流程图: T1中断流程图:
实验程序:
#include
#define TH (65536-46080)/256 //定时50ms 初值 #define TL (65536-46080)%256
sbit s1=P3^4; //定义按键s1 sbit s2=P3^5; //定义按键s2 sbit buz=P2^5; //定义蜂鸣器 char
led_mod[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //七段数码管0~9的值 unsigned char code
song1[]={0x54,0x32,0x52,0x88,0x64,0x82,0x62,0x58,0x54,0x12, //送别音码表
0x22,0x34,0x22,0x12,0x2c,0x54,0x32,0x52,0x84,0x74,
0x64,0x84,0x58,0x54,0x22,0x23,0x44,0x74,0x1c,0x64,
开始
Si 按下?
Flag_si=1,save=i
结束
开始
TR0=0,buz=~buz 装第i 首歌第j 个音符初值
第j 个音符时间到?
j++,count=0
TR0=1
结束
开始
TR1=0
装50ms 初值
统计50ms 计数了多少次,每计数一次,count++
TR1=1
结束
0x84,0x88,0x74,0x62,0x72,0x88,0x62,0x72,0x82,0x62,
0x62,0x52,0x32,0x12,0x2c,0x54,0x32,0x52,0x84,0x74,
0x64,0x84,0x58,0x54,0x22,0x32,0x44,0x74,0x1c,0x00};
unsigned char
song2[]={0x01,0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81,0x91,0x00}; //第二首歌音码表
unsigned int
hz[]={64603,64654,64751,64837,64876,64948,65012,65069,65095,65143};
//各种音符计数初值
int a=0,b=0; //a为音码表的高位,b为音码表的低位
int k=0,j=0,count=0,flag_s1=0,flag_s2=0,save=0;
void init(); //中断初始化
void main()
{
P2=0x08; //关蜂鸣器
P3=0x08; //键盘扫描
init(); //中断初始化
TH1=TH; //装50ms初值
TL1=TL;
while(1)
{
P3=0x08; //键盘扫描
P0=led_mod[save]; //显示歌曲代码
if(k)
{
if(k==1) //S1键按下
{
a=song1[j]/16;
b=song1[j]%16;
TH0=hz[a]/256; //装初值
TL0=hz[a]%256;
}
if(k==2) //S2键按下
{
a=song2[j]/16;
b=song2[j]%16;
TH0=hz[a]/256; //装初值
TL0=hz[a]%256;
}
k=0;
TR0=1;
TR1=1;
}
}
}
void init() //中断初始化程序
{
IE=0x8e;
TCON=0x04;
IP=0x04;
TMOD=0x11;
TR0=0;
TR1=0;
}
void time1(void) interrupt 1 //TO中断{
TR0=0;
buz=~buz;
if(flag_s1==1) //S1键按下{
a=song1[j]/16;
b=song1[j]%16;
TH0=hz[a]/256; //装初值
TL0=hz[a]%256;
}
if(flag_s2==1) //S2键按下
{
a=song2[j]/16;
b=song2[j]%16;
TH0=hz[a]/256; //装初值
TL0=hz[a]%256;
}
if(count==5*b) //音长
{
count=0;
j++;