本帖最后由 tyw 于 2010-12-14 10:54 编辑  
 
闹了半天,早点说清醋鸭,哈哈,别说滴滴响了,唱歌也没问题的拉.  
I/O有多的话,可用电阻衰减的方法调音量.(tmd,泥们老板以为在做扩音机啊,蜂鸣器巴不得它响一点呢,还调死马音量,撑,哈哈) 
 
;***************************************** 
;* 音乐子程序 MUSIC                                               * 
;* --------------------------------------------------* 
;* 中央c组里的A=440Hz                                           * 
;* 12个半音阶相邻关系是12√2 (2开12次方≈1.0594631)  * 
;* 例如 A=440Hz                                                   * 
;*     bB=440.00Hz x 1.0594631 = 466.16Hz             * 
;*      B=466.16Hz x 1.0594631 = 493.88Hz             * 
;*      C=493.88Hz x 1.0594631 = 523.25Hz             * 
;* 用定时器来模拟这个频率,精度取决于时钟快慢                * 
;* 一般小数点后保留一位,音准已可忍受了                        * 
;* 这是本人一个产品中的音乐单元,很完整,供爱好者参考.      * 
;***************************************** 
; 
        ORG     0000H 
        AJMP    CSH             ;主程序进入点 
        ORG     000BH 
        LJMP    TIM0            ;定时中断T0入口 
; 
;********** 
;* 初始化 * 
;********** 
; 
        ORG     0020H 
CSH:    MOV     R0,#7FH         ;内部RAM(00H~7FH)清零 
CSH1:   MOV     @R0,#00H 
        DJNZ    R0,CSH1 
        MOV     SP,#60H            ;堆栈60H~7FH,【使用89C51】 
        MOV     TMOD,#01H       ;TMOD=11H,T0作16位计数器(4M晶振) 
        CLR     TCON.4              ;T0禁止动作 
        SETB    IE.1                  ;T0允许中断 
        SETB    PT0                  ;T0中断优先 
        SETB    IE.7                  ;系统允许中断 
; 
;********** 
;* 主程序 * 
;********** 
; 
MAIN:   MOV     5CH,#00       ;取简码谱指针 
        LCALL   MUSIC 
        MOV     5CH,#49          ;取简码谱指针 
        LCALL   MUSIC 
        MOV     5CH,#66          ;取简码谱指针 
        LCALL   MUSIC 
        MOV     5CH,#100        ;取简码谱指针 
        LCALL   MUSIC 
        MOV     5CH,#108        ;取简码谱指针 
        LCALL   MUSIC 
        MOV     5CH,#136        ;取简码谱指针 
        LCALL   MUSIC 
        MOV     5CH,#174        ;取简码谱指针 
        LCALL   MUSIC 
        AJMP    MAIN 
; 
;************************* 
;* 音乐子程序 MUSIC      * 
;* 入口: 5CH←简码谱指针 * 
;************************* 
; 
MUSIC:  MOV     A,5CH           ;简码谱指针装入A 
        MOV     DPTR,#TABLE    ;至TABLE取简码 
        MOVC    A,@A+DPTR 
        MOV     R2,A                 ;取到的简码暂存于R2 
        JZ      END1                  ;是否取到00(结束码)? 
        ANL     A,#0FH              ;不是,则取低四位(节拍码) 
        MOV     R6,A                 ;将节拍码存入R6 
        MOV     A,R2                 ;将取到的简码再装入R2 
        SWAP    A                    ;高低四位交换 
        ANL     A,#0FH             ;取低四位(音符码) 
        JNZ     SING                 ;取到的音符码是否为0? 
        CLR     TR0                  ;是,则不发音 
        AJMP    D1                   ;跳到D1 
; 
SING:   DEC     A                  ;取到的音符码减1 
        MOV     4BH,A              ;存入(4BH) 
        RL      A                       ;乘2 
        MOV     DPTR,#TABLE1  ;至TABLE1取相对的高字节计数值 
        MOVC    A,@A+DPTR 
        MOV     TH0,A               ;取到的高字节存入TH0 
        MOV     4AH,A              ;取到的高字节存入(4AH) 
        MOV     A,4BH              ;再装入取到的音符码 
        RL      A                       ;乘2 
        INC     A                      ;加1 
        MOVC    A,@A+DPTR      ;至TABLE1取相对的低位 
        MOV     TL0,A              ;取到的低字节存入TL0 
        MOV     49H,A              ;取到的低字节存入(49H) 
        SETB    TR0                 ;启动TIMER0 
D1:     CALL    DELAY            ;基本单位时间1/4拍187毫秒 
        INC     5CH                 ;取简码谱指针加1 
        AJMP    MUSIC            ;取下一个码 
DD1:    RET 
; 
STOP:   NOP 
;       JB      P3.7,STOP1      ;在软件延时中掺插做其他动作 
;       SETB    P2.7              ;P2.7←"1" 
        NOP 
        NOP 
STOP0:  NOP 
        RET 
STOP1:  NOP 
;       JB      P3.6,STOP0      ;在软件延时中掺插做其他动作 
;       SETB    P2.6             ;P2.6←"1" 
        RET 
; 
END1:   CLR     TR0             ;停止TIMER0 
        RET 
; 
TIM0:   PUSH    A               ;将A的值暂存于堆栈区 
        PUSH    PSW             ;将PSW的值暂存于堆栈区 
        MOV     TL0,49H         ;重设计数值 
        MOV     TH0,4AH 
        CPL     P1.7              ;将输出端P1.1取反(P1.7接至无源蜂鸣器) 
        POP     PSW             ;至堆栈区取回PSW的值 
        POP     A                 ;至堆栈区取回A的值 
        RETI                      ;返回主程序 
; 
DELAY:  MOV     R7,#02          ;187毫秒 
D2:     MOV     R4,#24 
D3:     MOV     R3,#48 
        DJNZ    R3,$ 
        ACALL   STOP            ;在软件延时中掺插做其他动作 
        DJNZ    R4,D3 
        DJNZ    R7,D2 
        DJNZ    R6,DELAY        ;决定节拍 
        RET 
;                 .5   .6     .7    1 
TABLE1: DW      65111,65150,65199,65217   ;4M晶振时的定时中断时间常数 
;                  2    3     4     5                    ;若采用其它频率,则要根据乐音的 
        DW      65252,65283,65297,65323      ;频率计算,例中央C的A音为440Hz, 
;                  6    7     1`    2`                  ;440Hz=2.273ms,把T0设置为2.273ms 
        DW      65347,65367,65377,65394      ;中断即可发出A音. 
;                 3`    4`    #6 
        DW      65410,65417,65357 
; 
;*************************************************************** 
;* 音符代码  1  2  3  4  5  6  7  8  9  A  B  C   D  E   F   0             * 
;* 音高      .5 .6 .7  1  2  3  4  5  6  7  1` 2` 3` 4` 5` 休止          * 
;*-------------------------------------------------------------* 
;* 节拍代码  1   2   3   4    5        6     8    A     C    F                * 
;* 节拍     1/4 2/4 3/4 1 1(1/4) 1(1/2) 2 2(1/2) 3 3(3/4)             * 
;*-------------------------------------------------------------* 
;* 结束代码 00H                                                                   * 
;*-------------------------------------------------------------* 
;* 乐谱格式  每字节的高字节为音符代码,低字节为节拍代码                   *   
;*-------------------------------------------------------------*  
;* 例子:         ⑴    ⑵  ⑶    ⑷   ⑸   ⑹    ⑺   ⑻   ⑼   ⑽   ⑾      * 
;*      DB      A4H,02H,84H,02H,A4H,02H,84H,02H,D8H,04H,00H    * 
;*      ⑴ A→唱"7" , 4→ 1 拍                                                   * 
;*      ⑵ 0→休止  , 2→2/4拍                                                   *  
;*      ⑶ 8→唱"5" , 4→ 1 拍                                                   *  
;*      ⑷ 0→休止  , 2→2/4拍                                                  *  
;*      ⑸ A→唱"7" , 4→ 1 拍                                                   * 
;*      ⑹ 0→休止  , 2→2/4拍                                                  * 
;*      ⑺ 8→唱"5" , 4→ 1 拍                                                   *  
;*      ⑻ 0→休止  , 2→2/4拍                                                  * 
;*      ⑼ D→唱"3`", 8→ 2 拍                                                  * 
;*      ⑽ 0→休止  , 4→ 1 拍                                                   * 
;*      ⑾ 00H→乐曲结束                                                         * 
;*************************************************   
; 
TABLE: 
;【00】  
        DB      98H,02H,B4H,01H,94H,01H,68H,02H,94H,01H 
        DB      64H,01H,48H,02H,64H,01H,44H,01H,28H,02H 
        DB      64H,01H,94H,01H,B4H,01H,94H,01H,B4H,01H 
        DB      94H,01H,B4H,01H,D4H,01H,94H,01H,64H,01H 
        DB      44H,01H,64H,01H,98H,02H,01H,01H,00H 
;【49】  
        DB      A4H,02H,84H,02H,A4H,02H,84H,02H,D8H,04H 
        DB      C8H,01H,01H,01H,01H,01H,00H 
;【66】  
        DB      42H,52H,62H,72H,82H,92H,A2H,B2H,42H,52H 
        DB      62H,72H,82H,92H,A2H,B2H,00H 
;【100】 
        DB      61H,81H,B1H,D1H,B1H,81H,61H,00H 
;【108】 
        DB      11H,41H,61H,81H,61H,41H,11H,00H 
;【136】 
        DB      24H,04H,34H,04H,44H,04H,54H,04H,64H,04H,44H,04H,64H,04H,94H,04H 
        DB      83H,01H,93H,01H,83H,01H,63H,01H,46H,02H,66H,02H 
        DB      91H,21H,91H,21H,91H,21H,91H,21H,94H,00H 
;【174】 
        DB      94H,04H,A4H,04H,B4H,04H,C4H,04H,D4H,04H 
        DB      B4H,04H,D8H,08H,C4H,04H,F4H,04H,CCH,00H 
; 
                  END 
 |