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