用单片机设计的电子琴,AT89S51 KEYBOARD
关键字:AT89S51,电子琴电路
1.实验任务(1).由4X4组成16个按钮矩阵,设计成16个音。 (2).可随意弹奏想要表达的音乐。 2.电路原理图 3.系统板硬件连线 (1).把“单片机系统”区域中的P1.0端口用导线连接到“音频放大模块”区域中的SPK IN端口上; (2).把“单片机系统“区域中的P3.0-P3.7端口用8芯排线连接到“4X4行列式键盘”区域中的C1-C4 R1-R4端口上; 4.相关程序内容 (1).4X4行列式键盘识别; (2).音乐产生的方法; 一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。现在以单片机12MHz晶振为例,例出高中低音符与单片机计数T0相关的计数值如下表所示
音符 |
频率(HZ) |
简谱码(T值) |
|
音符 |
频率(HZ) |
简谱码(T值) |
低1 DO |
262 |
63628 |
# 4 FA# |
740 |
64860 |
#1 DO# |
277 |
63731 |
中 5 SO |
784 |
64898 |
低2 RE |
294 |
63835 |
# 5 SO# |
831 |
64934 |
#2 RE# |
311 |
63928 |
中 6 LA |
880 |
64968 |
低 3 M |
330 |
64021 |
# 6 |
932 |
64994 |
低 4 FA |
349 |
64103 |
中 7 SI |
988 |
65030 |
# 4 FA# |
370 |
64185 |
高 1 DO |
1046 |
65058 |
低 5 SO |
392 |
64260 |
# 1 DO# |
1109 |
65085 |
# 5 SO# |
415 |
64331 |
高 2 RE |
1175 |
65110 |
低 6 LA |
440 |
64400 |
|
# 2 RE# |
1245 |
65134 |
# 6 |
466 |
64463 |
高 3 M |
1318 |
65157 |
低 7 SI |
494 |
64524 |
高 4 FA |
1397 |
65178 |
中 1 DO |
523 |
64580 |
# 4 FA# |
1480 |
65198 |
# 1 DO# |
554 |
64633 |
高 5 SO |
1568 |
65217 |
中 2 RE |
587 |
64684 |
# 5 SO# |
1661 |
65235 |
# 2 RE# |
622 |
64732 |
高 6 LA |
1760 |
65252 |
中 3 M |
659 |
64777 |
# 6 |
1865 |
65268 |
中 4 FA |
698 |
64820 |
高 7 SI |
1967 |
65283 |
下面我们要为这个音符建立一个表格,有助于单片机通过查表的方式来获得相应的数据 低音0-19之间,中音在20-39之间,高音在40-59之间 TABLE: DW 0,63628,63835,64021,64103,64260,64400,64524,0,0 DW 0,63731,63928,0,64185,64331,64463,0,0,0 DW 0,64580,64684,64777,64820,64898,64968,65030,0,0 DW 0,64633,64732,0,64860,64934,64994,0,0,0 DW 0,65058,65110,65157,65178,65217,65252,65283,0,0 DW 0,65085,65134,0,65198,65235,65268,0,0,0 DW 0 2、音乐的音拍,一个节拍为单位(C调)
曲调值 |
DELAY |
|
曲调值 |
DELAY |
调4/4 |
125ms |
|
调4/4 |
62ms |
调3/4 |
187ms |
|
调3/4 |
94ms |
调2/4 |
250ms |
|
调2/4 |
125ms |
对于不同的曲调我们也可以用单片机的另外一个定时/计数器来完成。 下面就用AT89S51单片机产生一首“生日快乐”歌曲来说明单片机如何产生的。 在这个程序中用到了两个定时/计数器来完成的。其中T0用来产生音符频率,T1用来产生音拍。 5.程序框图
6.汇编源程序 KEYBUF EQU 30H STH0 EQU 31H STL0 EQU 32H TEMP EQU 33H ORG 00H LJMP START ORG 0BH LJMP INT_T0 START: MOV TMOD,#01H SETB ET0 SETB EA WAIT: MOV P3,#0FFH CLR P3.4 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY1 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY1 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK1 MOV KEYBUF,#0 LJMP DK1 NK1: CJNE A,#0DH,NK2 MOV KEYBUF,#1 LJMP DK1 NK2: CJNE A,#0BH,NK3 MOV KEYBUF,#2 LJMP DK1 1NK3: CJNE A,#07H,NK4 MOV KEYBUF,#3 LJMP DK1 NK4: NOP DK1: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK1A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK1A CLR TR0 NOKEY1: MOV P3,#0FFH CLR P3.5 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY2 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY2 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK5 MOV KEYBUF,#4 LJMP DK2 NK5: CJNE A,#0DH,NK6 MOV KEYBUF,#5 LJMP DK2 NK6: CJNE A,#0BH,NK7 MOV KEYBUF,#6 LJMP DK2 NK7: CJNE A,#07H,NK8 MOV KEYBUF,#7 LJMP DK2 NK8: NOP DK2: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK2A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK2A CLR TR0 NOKEY2: MOV P3,#0FFH CLR P3.6 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY3 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY3 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK9 MOV KEYBUF,#8 LJMP DK3 NK9: CJNE A,#0DH,NK10 MOV KEYBUF,#9 LJMP DK3 NK10: CJNE A,#0BH,NK11 MOV KEYBUF,#10 LJMP DK3 NK11: CJNE A,#07H,NK12 MOV KEYBUF,#11 LJMP DK3 NK12: NOP DK3: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK3A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK3A CLR TR0 NOKEY3: MOV P3,#0FFH CLR P3.7 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY4 LCALL DELY10MS MOV A,P3 ANL A,#0FH XRL A,#0FH JZ NOKEY4 MOV A,P3 ANL A,#0FH CJNE A,#0EH,NK13 MOV KEYBUF,#12 LJMP DK4 NK13: CJNE A,#0DH,NK14 MOV KEYBUF,#13 LJMP DK4 NK14: CJNE A,#0BH,NK15 MOV KEYBUF,#14 LJMP DK4 NK15: CJNE A,#07H,NK16 MOV KEYBUF,#15 LJMP DK4 NK16: NOP DK4: MOV A,KEYBUF MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,KEYBUF MOV B,#2 MUL AB MOV TEMP,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC TEMP MOV A,TEMP MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 DK4A: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ DK4A CLR TR0 NOKEY4: LJMP WAIT DELY10MS: MOV R6,#10 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET INT_T0: MOV TH0,STH0 MOV TL0,STL0 CPL P1.0 RETI TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H TABLE1: DW 64021,64103,64260,64400 DW 64524,64580,64684,64777 DW 64820,64898,64968,65030 DW 65058,65110,65157,65178 END 7.C语言源程序 #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; unsigned char temp; unsigned char key; unsigned char i,j; unsigned char STH0; unsigned char STL0; unsigned int code tab[]={64021,64103,64260,64400, 64524,64580,64684,64777, 64820,64898,64968,65030, 65058,65110,65157,65178}; void main(void) { TMOD=0x01; ET0=1; EA=1; while(1) { P3=0xff; P3_4=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=0; break; case 0x0d: key=1; break; case 0x0b: key=2; break; case 0x07: key=3; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%6; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } P3=0xff; P3_5=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=4; break; case 0x0d: key=5; break; case 0x0b: key=6; break; case 0x07: key=7; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%6; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } P3=0xff; P3_6=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=8; break; case 0x0d: key=9; break; case 0x0b: key=10; break; case 0x07: key=11; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%6; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } P3=0xff; P3_7=0; temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp & 0x0f; if (temp!=0x0f) { temp=P3; temp=temp & 0x0f; switch(temp) { case 0x0e: key=12; break; case 0x0d: key=13; break; case 0x0b: key=14; break; case 0x07: key=15; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%6; TR0=1; temp=temp & 0x0f; while(temp!=0x0f) { temp=P3; temp=temp & 0x0f; } TR0=0; } } } } void t0(void) interrupt 1 using 0 { TH0=STH0; TL0=STL0; P1_0=~P1_0; }
|