1 ; 8253定时计数器演奏音乐 2 3 ; 8253定时计数器T2输出用于音频驱动 演奏《一闪一闪亮晶晶》 4 5 ; (A9)CS -- (B8)300 6 ; (A12)Φ -- (A11)1A ;输入4.9152MHz 7 ; (A9)CLK2 -- (A11)1QD ;输出307.2KHz 8 ; (A9)GATE2 -- (A10)+5V 9 ; (A9)OUT2 -- 上板喇叭 10 11 CS8253 EQU 0303H ;8253端口地址 12 TCON2 EQU 0302H ;8253的通道2端口地址 13 TCON1 EQU 0301H ;8253的通道1端口地址 14 TCON0 EQU 0300H ;8253的通道0端口地址 15 16 data segment 17 state DB 3 18 ;音符数据 19 TFREQ DW 264,264,396,396,440,440,396 ; 1 1 5 5 6 6 5 20 DW 352,352,330,330,297,297,264 ; 4 4 3 3 2 2 1 21 DW 396,396,352,352,330,330,297 ; 5 5 4 4 3 3 2 22 DW 396,396,352,352,330,330,297 ; 5 5 4 4 3 3 2 23 DW 264,264,396,396,440,440,396 ; 1 1 5 5 6 6 5 24 DW 352,352,330,330,297,297,264,0 ; 4 4 3 3 2 2 1 25 26 ;节拍数据 27 TDLY DW 6000,6000,6000,6000,6000,6000,12000 28 DW 6000,6000,6000,6000,6000,6000,12000 29 DW 6000,6000,6000,6000,6000,6000,12000 30 DW 6000,6000,6000,6000,6000,6000,12000 31 DW 6000,6000,6000,6000,6000,6000,12000 32 DW 6000,6000,6000,6000,6000,6000,12000 33 34 data ends 35 36 CODE SEGMENT 37 ASSUME CS:CODE, ds:data 38 39 START: mov ax, data 40 mov ds, ax 41 42 restart: 43 MOV SI,OFFSET TFREQ 44 MOV BX,OFFSET TDLY 45 46 FREQ: MOV DI,[SI] 47 CMP DI,0 48 ;JE START 49 je next 50 51 CALL SOUND 52 ADD SI, 2 ;转到下一个音符 53 ADD BX, 2 ;转到下一个节拍 54 JMP FREQ 55 56 SOUND: MOV DX,CS8253 ;8253初始化 57 MOV AL,0B6H 58 OUT DX,AL 59 MOV DX,2 60 MOV AX,307 ;307.2KHz 61 DIV DI 62 MOV DX,TCON2 63 OUT DX,AL 64 MOV AL,AH 65 OUT DX,AL 66 67 MOV AX,[BX] 68 69 70 SLOOP: MOV CX,0018H ;延时子程序 71 LOOP $ 72 73 DEC AX 74 JNZ SLOOP 75 RET 76 77 next:;mov cx, word ptr [state] 78 mov dl, state 79 dec dl 80 mov state, dl 81 82 cmp dl, 0 83 je stop 84 jmp restart 85 86 stop:mov ah, 4ch 87 int 21h 88 89 CODE ENDS 90 END START 91 92 ****************************************************** 93 94 ; 8253定时计数器演奏音乐 95 96 ; 8253定时计数器T2输出用于音频驱动 演奏《一闪一闪亮晶晶》 97 98 ; (A9)CS -- (B8)300 99 ; (A12)Φ -- (A11)1A ;输入4.9152MHz 100 ; (A9)CLK2 -- (A11)1QD ;输出307.2KHz 101 ; (A9)GATE2 -- (A10)+5V 102 ; (A9)OUT2 -- 上板喇叭 103 104 data segment 105 state DB 3 106 ;音符数据 107 TFREQ DW 264,264,396,396,440,440,396 ; 1 1 5 5 6 6 5 108 DW 352,352,330,330,297,297,264 ; 4 4 3 3 2 2 1 109 DW 396,396,352,352,330,330,297 ; 5 5 4 4 3 3 2 110 DW 396,396,352,352,330,330,297 ; 5 5 4 4 3 3 2 111 DW 264,264,396,396,440,440,396 ; 1 1 5 5 6 6 5 112 DW 352,352,330,330,297,297,264,0 ; 4 4 3 3 2 2 1 113 114 ;节拍数据 115 TDLY DW 6000,6000,6000,6000,6000,6000,12000 116 DW 6000,6000,6000,6000,6000,6000,12000 117 DW 6000,6000,6000,6000,6000,6000,12000 118 DW 6000,6000,6000,6000,6000,6000,12000 119 DW 6000,6000,6000,6000,6000,6000,12000 120 DW 6000,6000,6000,6000,6000,6000,12000 121 122 data ends 123 124 CODE SEGMENT 125 ASSUME CS:CODE, ds:data 126 127 START: mov ax, data 128 mov ds, ax 129 130 restart: 131 MOV SI,OFFSET TFREQ ;置地址指针 132 MOV BX,OFFSET TDLY 133 134 FREQ: MOV DI,[SI] ;寄存器间接寻址 135 CMP DI,0 ;0是音符表的终止标志 136 je next ;如果DI=0 表明已经结束一次播放 跳转到next 137 138 CALL SOUND ;段内间接调用子程序sound 139 140 ADD SI, 2 ;转到下一个音符 141 ADD BX, 2 ;转到下一个节拍 142 JMP FREQ ;处理发声当前这个音符 143 144 SOUND: MOV DX, 303H 145 MOV AL,10110110B 146 OUT DX,AL ;8253初始化 送控制字 147 148 MOV DX,2 ;进行的是字运算 149 MOV AX,307 ;307.2KHz 150 DIV DI ;(dx:ax)/di 结果存到ax 151 152 MOV DX, 302H ;端口2 153 OUT DX,AL ;计算计数初值 154 MOV AL,AH ;分高低8位写计数初值 155 OUT DX,AL 156 157 MOV AX,[BX] ;取节拍数字 158 159 160 SLOOP: MOV CX,0018H ;延时子程序 161 LOOP $ ;执行一条loop指令需要17个时钟周期 162 163 DEC AX ;控制节拍数 164 JNZ SLOOP 165 RET 166 167 next: 168 mov dl, state ;取内存中的state的值 169 dec dl ;自减 170 mov state, dl ;更新state 171 172 cmp dl, 0 173 je stop ;若dl=0 表明循环次数已够 转去执行stop 174 jmp restart ;否则转去执行restart 175 176 stop:mov ah, 4ch ;返回DOS结束 177 int 21h 178 179 CODE ENDS 180 END START