键盘电子乐器

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于AT89S51键盘电子乐器的设计专业班级:

设计者:

指导老师:

设计时间:

一、设计目的:键盘电子乐器

二、功能要求:

利用单片机AT89C51端口作为键盘接口,设计一个具有2个八度音阶的键盘乐器,音阶键不少于16个,采用扫描方式管理键盘,音域

范围自行定义。也可播放1-3首音乐三、方案论证:

系统框图设计如图所示:

四、系统硬件设计:

系统硬件设计如图2所示:

图2 系统硬件设计

五、软件设计:

(1)弹奏程序流程图如图3所示:

图3流程图(2)播放歌曲程序流程图如图4

图4 流程图(2)程序:

/***** 文件名:

键盘电子乐器.c*****/

#include

#include

#define uchar unsigned char

#define uint unsigned int

uchar Count;

void Play_Song(uchar i);

sbit ge=P3^0; //歌曲开关按键

sbit Speak =P3^7; //扬声器控制脚

uint FreqTemp;

unsigned int code Freqtab[] = { //定时半周期的初始值64021,64103,64260,64400, //低音3 4 5 6

64524,64580,64684,64777, //低音7,中音1 2 3

64820,64898,64968,65030, //中音4 5 6 7

65058,65110,65157,65178 //高音1 2 3 4

};

//关于半周期的初始值与频率的关系,可见:

/************************************************************* * 函数功能: 用扫描法读P1 外接4×4 键盘

* 函数返回: 按下键:返回0~15、如无键按下:返回16

**************************************************************/ uchar Keyscan(void)

{ uchar i, j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};

for(j = 0; j < 4; j++) //循环四次,扫描四行

{ P1 = Buffer[j]; //在低四位分别输出一个低电平_nop_();

temp = 0x80; //计划先读出P1.7位

for(i = 0; i < 4; i++) //循环四次,检查四列

{ if(!(P1 & temp)) //从高四位,截取1位

{

return (i + j * 4); //返回取得的按键值

}

temp >>= 1; //往右边一位

}

}

return 16; //没有键按下就返回16

}

/************************************************************** * 函数功能:按键数码管显示

* 输入: k (键盘数值)

***************************************************************/ void Display(uchar k) //数码管显示

{ if(k<8)

P2 =0xC7 ;

else

P2=0x89 ;

}

void mmkey(void)

{ uchar Key_Value = 16, Key_Temp1, Key_Temp2;//读出的键值TMOD = 0x01; //T0定时方式1

ET1 = 1; //允许T1中断

EX1 = 1; //允许外部中断INT1中断允许

EA = 1; //开总中断

while(1)

{ if(ge==0)

Play_Song(0); //Play_Song(0)为祝你平安Play_Song(1)为路边的野花你不要采TR1 = 0; //暂不发音

Key_Temp1 = Keyscan(); //读入按键

if(Key_Temp1 != 16) //有键按下

{ Display(Key_Value); //显示键值、延时消抖

Key_Temp2 = Keyscan(); //再读一次

if (Key_Temp1 == Key_Temp2)//两次相等

{ Key_Value = Key_Temp1; //就确认下来

FreqTemp = Freqtab[Key_Value]; //根据键值,取出定时半周期的初始值

Display(Key_Value); //显示

TR1 = 1; //启动定时器,发音

while (Keyscan() < 16); //等待释放

Speak = 0; //停止发音

}

}

}

}

void T1_INT(void) interrupt 3

{ TL1 = FreqTemp; //载入定时半周期的初始值

TH1 = FreqTemp >> 8;

Speak = ~Speak; //发音

}

/*以下数组是音符编码*/

unsigned char code SONG[] ={ //祝你平安

0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,

0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,

0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,

0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,

0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,

0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,

0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,

0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,

0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,

0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,

0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,

0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,

0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,

0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,

//路边的野华不要采

0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,0x20,

0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,

0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0xFF,

0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,

0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,

相关文档
最新文档