图中脉冲信号的频率为307.2KHz.
我这里实现了不同的乐曲分别是小星星,友谊地久天长和卖报歌,按下开关一是小星星,开关二是友谊地久天长,开关三是卖报歌:
DATAS SEGMENT
;此处输入数据段代码
IOYO equ 0C400h;对应的端口地址
IOY1 equ 0C440h
MY8253_COUNT_0 equ IOYO+00H*4;8254计数器0端口1地址
MY8253_COUNT1 equ IOYO+01H*4;8254计数器1端口2地址
MY8253_COUNT2 equ IOYO+02H*4;8254计数器2端口3地址
MY8253_MODE equ IOYO+03H*4;8254控制器地址
MY8255_A equ IOY1+00H*4;8255计数器端口1地址
MY8255_B equ IOY1+01H*4;8255计数器端口2地址
MY8255_C equ IOY1+02H*4;8255计数器端口3地址
MY8255_MODE equ IOY1+03H*4;8254控制器地址
TFREQ dw 264,264,396,396,440,440,396
dw 352,353,330,330,297,297,264
dw 396,396,352,352,330,330,297
dw 396,396,352,352,330,330,297
dw 264,264,396,396,440,440,396
dw 352,352,330,330,297,297,264,0
TDLY dw 6000,6000,6000,6000,6000,6000,12000
dw 6000,6000,6000,6000,6000,6000,12000
dw 6000,6000,6000,6000,6000,6000,12000
dw 6000,6000,6000,6000,6000,6000,12000
dw 6000,6000,6000,6000,6000,6000,12000
dw 6000,6000,6000,6000,6000,6000,12000
TFREQ2 dw 371,495,495,495,624,556,495,556,624
dw 495,495,624,742,833,833,833,742,624
dw 624,495,556,495,556,624,495,416,416,371
dw 495,833,742,624,624,495,556,495,556,833
dw 742,624,624,742,833,990,742,624,624,495
dw 556,495,556,624,495,416,416,371,495,0
TDLY2 dw 6000,9000,3000,6000,6000,9000,3000,6000,6000
dw 9000,3000,6000,6000,18000,1500,4500,9000
dw 3000,6000,6000,9000,3000,6000,6000,9000
dw 3000,6000,6000,18000,6000,9000,3000,6000
dw 6000,9000,3000,6000,6000,9000,3000,6000
dw 6000,18000,6000,9000,3000,6000,6000,9000
dw 3000,6000,6000,9000,3000,6000,6000,18000
TFREQ3 dw 525,525,525,525,525,525,441,525,589
dw 525,441,393,441,525,525,441,525
dw 441,393,350,441,393,441,441,393
dw 661,350,393,589,589,525,441,589
dw 525,525,441,393,441,525,525,441
dw 393,441,525,441,393,441,661,350
dw 393,441,350,0
TDLY3 dw 3000,3000,3000,3000,3000,3000,3000,3000,3000
dw 3000,3000,3000,3000,3000,3000,3000,3000
dw 3000,3000,3000,3000,3000,3000,3000,3000
dw 3000,3000,3000,3000,3000,3000,3000,3000
dw 3000,3000,3000,3000,3000,6000,3000,3000
dw 3000,3000,3000,3000,3000,3000,3000,3000
dw 3000,3000,6000
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
;此处输入代码段代码
mov dx,MY8255_B;输入信号
in al,dx
mov dx,MY8255_MODE
mov al,82h;1000 0010
out dx,al
K:
mov dx,MY8255_B;输入信号
in al,dx
cmp al,0FEh
je K1
cmp al,0FDh
je k2
cmp al,0FBh
je k3
;cmp al,0f7h
;je k4
;jmp Turn_out;熄灭
jmp k
k1:
mov dx,MY8255_A
mov al,00h;门控位高电平允许计数
out dx,al
mov si,offset tfreq
mov bx,offset tdly
call PlayMusic
jmp k
k2:
mov dx,MY8255_A
mov al,00h;门控位高电平允许计数
out dx,al
mov si,offset tfreq2
mov bx,offset tdly2
call PlayMusic
jmp k
k3:
mov dx,MY8255_A
mov al,00h;门控位高电平允许计数
out dx,al
mov si,offset tfreq3
mov bx,offset tdly3
call PlayMusic
jmp k
PlayMusic proc near
FREQ:
mov di,[si]
cmp di,0
je stop
call sound
add si,2;转到下一个音符
add bx,2;转到下一个节拍
jmp freq
stop:
mov dx,MY8255_A
mov al,01h;门控位低电平禁止计数
out dx,al
ret
playmusic endp
sound proc near
mov dx,MY8253_MODE;8253初始化
mov al,0b6h;10通道2,11先读写高字节,后读写低字节011方式3,0二进制计数
out dx,al
mov dx,2
mov ax,307;307.2KHz
div di
mov dx,MY8253_COUNT2
out dx,al
mov al,ah
out dx,al
mov ax,[bx]
sloop:
mov cx,0018h;延时程序
LOOP $
dec ax
jnz sloop
ret
sound endp
exit:
MOV AH,4CH
INT 21H
CODES ENDS
END START
在做改进部分的时候我发现一个问题,就是这个实验的切换,比如在两首乐曲之间进行切换的时候,一首乐曲的结尾一直发最后一个音,我觉得很奇怪,不是没有输入频率进去怎么还在发声,后来参考8253方式三,才发现原来问题在于只有GATE位为高电平,8253就会继续输出方波,后来我改进成了一首乐曲完成后GATE位输出低电平使8253停止输出波形,这样才改进好。这个问题可能大家也会遇到就提出来了。
这个程序参考了https://blog.csdn.net/weixin_30390075/article/details/97020412?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase大家可以查看原文章。
补充:运行使使能信号:
时钟信号设置: