| 
 22. 电子琴  1. 实验任务  (1. 由4X4组成16个按钮矩阵,设计成16个音。  (2. 可随意弹奏想要表达的音乐。  2. 电路原理图  file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image001.jpg 图4.22.1  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: DW0,63628,63835,64021,64103,64260,64400,64524,0,0  DW0,63731,63928,0,64185,64331,64463,0,0,0  DW0,64580,64684,64777,64820,64898,64968,65030,0,0  DW0,64633,64732,0,64860,64934,64994,0,0,0  DW0,65058,65110,65157,65178,65217,65252,65283,0,0  DW0,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. 程序框图  file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image002.gif 图4.22.2  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 
NK3: 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 <AT89X51.H> 
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]%256; 
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]%256; 
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]%256; 
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]%256; 
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; 
}    
 |