1.实验任务
(1).由4X4组成16个按钮矩阵,设计成16个音。
(2).可随意弹奏想要表达的音乐。
2.电路原理图

                                                                           图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:        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.程序框图


                      图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 
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; 
}