搜索
您的当前位置:首页正文

键盘电子乐器

来源:哗拓教育


基于AT89S51键盘电子乐器的设计

专业班级:

设计者:

指导老师:

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

二、功能要求:

利用单片机AT89C51端口作为键盘接口,设计一个具有2个八度音阶的键盘乐器,音阶键不少于16个,采用扫描方式管理键盘,音域范围自行定义。也可播放1-3首音乐

三、方案论证:

系统框图设计如图所示:

四、系统硬件设计:

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

2

图2 系统硬件设计

五、软件设计:

3

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

图3流程图

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

4

图4 流程图

(2)程序:

/***** 文件名 :

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

#include

5

#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

6

};

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

/*************************************************************

* 函数功能 : 用扫描法读 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++) //循环四次,检查四列

7

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

{

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

}

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

}

}

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

}

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

* 输入 : k (键盘数值)

***************************************************************/ 8

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)

9

{ 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); //等待释放

10

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,

11

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,

12

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,0x2

13

B,0x40,

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

0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20,0x10,0x1C,0x10,

0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F,0x05,0x20,0x10,

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

0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,

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

0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,0x00,

};

/********************************************************************

14

* 名称 : Time0_Init()

* 功能 : 定时器的初始化,定时时间可用光碟中软件计算,11.0592MZ晶振,10ms

* 输入 : 无

* 输出 : 无

***********************************************************************/

void Time0_Init()

{ TMOD = 0x01;

IE = 0x82;

TH0 = 0xDC;

TL0 = 0x00;

}

// 名称 : Time0_Int()

//功能 : 定时器中断,中断中实现 Count 加一

15

void Time0_Int() interrupt 1

{ TH0 = 0xDC;

TL0 = 0x00;

Count++; //长度加1

}

/********************************************************************

* 名称 : Delay_xMs()

* 功能 : 延时子程序,经过软件调试,测得延时程序大概为55us.

* 输入 : x

* 输出 : 无

***********************************************************************/

void Delay_xMs(uint x)

{ uint i,j;

16

for(i=0; i{

for(j=0;j<3; j++);

}

}

/********************************************************************

* 名称 : Play_Song()

* 功能 : 播放扬声器器控制程序

* 输入 : i (选择播放哪首歌曲,0为“祝你平安”,1为“路边的野花你不要采”* 输出 : 无

***********************************************************************/

void Play_Song(uchar i)

{ uchar Temp1,Temp2;

17

uint Addr;

Count = 0; //中断计数器清0

Addr = i * 217;

while(1)

{ Temp1 = SONG[Addr++];

if (Temp1 == 0xFF) //休止符

{

TR0 = 0;

Delay_xMs(100);

}

else if (Temp1 == 0x00) //歌曲结束符

{

return;

18

}

else

{ Temp2 = SONG[Addr++];

TR0 = 1; while(1)

{

Speak = ~Speak; Delay_xMs(Temp1);

if(Temp2 == Count)

{

Count = 0;

break;

}

//计时 开始

//P3.7开始发声

19

}

}

if(ge==1) break; }

}

void Main()

{

Time0_Init(); //定时器0中断初始化

while(1)

{ mmkey();

}

}

六、仿真图:如 图 5 所示

20

图5 仿真图

七、心得体会:

这次设计从硬件方面来讲不是很难,程序也相对长一点,但都是书本上所学的知识,主要是中断及其服务程序的编写。在protues上仿真,则起到很好的效果。经过多次调试、修改才得以出结果。将程序烧入芯片,调试成功后,可弹奏自己想要的旋律。同时可以播放一两首示例歌曲,但是也有不足之处的,声音有点杂,不是很稳定。

经过本次课程设计,我们比较好的把理论知识与实践相结合,而我们也在本次设计中收获不少。设计过程中,首先,对于C语言多了一层了解,其次,还有硬件的接线,还有8051芯片的引脚方面,都让我们收获不少。加强了自身的动手能力,同时也感谢辅导老师的细心辅导和教诲。

21

因篇幅问题不能全部显示,请点此查看更多更全内容

Top