微原第三次实验
刚转了一个汇编播放器的博客,后面发现需要移植的东西比较多,那个就当学习了,提示信息很全面,人机交互比较好。
实验前预习的时候参考这个写了一个欢乐颂的程序,实验时改成最炫民族风了,结果忘拷贝回来,只好把原版的代码发上来。
<1>蜂鸣器的工作方式
以前做单片机蜂鸣器发声的时候,蜂鸣器在三极管的C极,B极接IO口,高电平时候,be之间导通,ce之间通过电流,蜂鸣器振动发声。
这次做的时候,发现需要定时器产生一定频率的波。
用蜂鸣器做音乐发声的比较小,当个提示音就行。
<2>算出低中高音的频率,通过输出频率给蜂鸣器来发出不同的声音。
<3>需要一段乐谱
<4>每个音符之后有一定的间隔,也就是延时
<5>每个音符播放出后进入键盘中断,若有键按下则退出。
<6>开始播放时会讲这时需要播放的乐符的频率送入蜂鸣器,加延时后播放下一个,需要计算乐符的长度。
DATA SEGMENT
;Count number
LOU DB 122,108,97,91,81,72,64 ;三种音调段的频率
MID DB 61,54,48,45,40,36,32
HIG DB 30,27,24,22,20,18,16
;Song huanlesong
BOK DB 3,3,4,5,5,4,3,2,1,1,2,3,3,2,2 ;乐谱
DB 3,3,4,5,5,4,3,2,1,1,2,3,2,1,1
DB 2,2,3,1,2,3,4,3,1,2,3,4,3,2,1,2,5,3
DB 3,3,4,5,5,4,3,2,1,1,2,3,2,1,1
LEN EQU $-BOK ;How many chars. ;长度
;TON 1-LOW,2-MID,3-HIG
TON DB 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 ;音调段的选择
DB 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
DB 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2
DB 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
;RHY 1-Quarter beat;2-Half beat
;4-One beat;8-Two beat;12-Three beat.
RHY DB 4,4,4,4,4,4,4,4,4,4,4,4,4,2,2 ;延时比例
DB 4,4,4,4,4,4,4,4,4,4,4,4,4,2,2
DB 4,4,4,4,4,2,2,4,4,4,2,2,4,4,4,4,4,4
DB 4,4,4,4,4,4,4,4,4,4,4,4,4,2,2
KEY DB 21H,0F4H,0F1H,39H,0D9H,0DDH,61H; 0~7 char code
TBOK DB 0
TTON DB 0 ;暂存
TRHY DB 0
COUNT DB 0
DATA ENDS
;-------------------------------------------------------------
STACK SEGMENT STACK 'STACK'
DB 50 DUP(?)
STACK ENDS
;-------------------------------------------------------------
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACK
;-------------------------------------------------------------
DELAY MACRO TIME ;Delay time
LOCAL LOPA
PUSH CX
MOV AX,TIME ;User can control time
LOPA: MOV CX,00H
LOOP $
DEC AX
JNZ LOPA
POP CX
ENDM
;-------------------------------------------------------------
MUSIC MACRO ;Write count number, music on
MOV AL,COUNT ;First get count number.
MOV DX,0E820H ;Use Counter 0
OUT DX,AL ;Write counter 0
ENDM
;-------------------------------------------------------------
READ PROC NEAR ;Read one note/rhyme/tone
;BX is offset, means where to find
;Result is saved in memory
MOV AL,BOK[BX]
XOR AH,AH
MOV SI,AX
DEC SI
MOV TBOK,AL ;Save note
MOV AL,RHY[BX]
MOV TRHY,AL ;Save rhyme
MOV AL,TON[BX]
CMP AL,1
JE ISLOW
CMP AL,2
JE ISMID
CMP AL,3
JE ISHIG
ISLOW:MOV AL,LOU[SI] ; To find counter
JMP EXITR
ISMID:MOV AL,MID[SI]
JMP EXITR
ISHIG:MOV AL,HIG[SI]
EXITR:MOV COUNT,AL ;Save count value
RET
READ ENDP
;-------------------------------------------------------------
RHYME PROC NEAR ;Control rhyme
MOV AL,TRHY
MOV AH,0FFH ;AH is time of Quarter beat
MUL AH
DELAY AX ;Rhyme, delay time in AX
RET
RHYME ENDP
;-------------------------------------------------------------
DISP PROC NEAR ;Display note being played
MOV DX,0E800H
MOV AL,BOK[BX] ;Get note char
XOR AH,AH
MOV DI,AX
DEC DI
MOV AL,KEY[DI] ;Get char code
OUT DX,AL
MOV AL,00000001B ;Only one digit on
MOV DX,0E801H
OUT DX,AL ;Control which LED on
RET
DISP ENDP
;-------------------------------------------------------------
MAIN: ;Main program start here
MOV AX,DATA
MOV DS,AX
MOV ES,AX
MOV DX,0E823H ;Initialize 8253
MOV AL,00010110B ;Use counter 0
OUT DX,AL
MOV AL,80H ;initialize 8255
MOV DX,0E803H
OUT DX,AL
PLAY:MOV CX,LEN ;Get book's length
XOR BX,BX ;Record current char being played
LOP: CALL READ ;Read note/rhyme/tone
CALL DISP ;Display note on LED
MUSIC ;Play music now
CALL RHYME ;Control rhyme
INC BX ;Next note
MOV AH, 0BH ;Test keyboard ;键盘中断
INT 21H
OR AL, AL
JNZ OVER ;Keyboard pressed, quit program
LOOP LOP
OVER:MOV DX, 0E823H ;Reset 8253A
MOV AL, 16H
OUT DX, AL
MOV AX,4C00H ;Back to DOS
INT 21H
;-------------------------------------------------------------
CODE ENDS
END MAIN