⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 单片机演奏多首音乐通用程序.asm

📁 这是2008年stc程序个人设计汇总
💻 ASM
字号:
org 00h
;mov 96h,#00111111b;p2M1

mov 8eh,#0   ;允许使用内部扩展的ram 
jmp cfg

org 0bh
jmp t0int

org 1bh
jmp t1int



;40保存设定时间,41保存A分数,42保存B分数,43保存当前时间(正在计时),44保存发声地址

cfg: mov 55h,#20

mov 40h,#30  ;开机时的初始分数
mov 41h,#00  ;左计分
mov 42h,#00   ;右计分
mov 43h,#30  ;读取初始时间从40读来
mov 5dh,#14;发开机声,可以分别查表不同的发声频率,不同的发声时间

mov r2,#1;工作模式,单机分别模式双机同时模式


mov tmod,#00100010b;t1工作方式二自动装入
mov th0,#245 ;12MHz时,1US*50=50us(20KHz,0.05ms)扫描一下转向记数
setb tr0
setb et0 
setb ea



main:
call js
call disp

call key1
call key2
call key3
call run1
jb 10h, main
call run2
call run3
jmp main 


key1:jb 09h,k1edd
setb 09h
jb p2.7,k1ed
jb 08h,k1edd
setb 08h
mov r0,#15
mov a,40h
cjne a,#90,rr10
mov 40h,#15
rr10:inc 40h
djnz r0,rr10
mov 43h,40h
clr 11h   ;允许倒计时和加分
ret
k1ed:clr 08h 
k1edd:ret



key2:

k2ed:ret
key3:

k3ed:ret

run1:jb 0fh,r1ed
setb 0fh
dec 43h
clr 10h ;允许计分
mov a,43h
cjne a ,#0, rrrr
setb 10h ;不许计分
setb 11h;还要加个不充再减

rrrr:mov a,#10
cjne a,43h,$+3
jc r1ed
mov 5dh ,#0  ;发声
r1ed:ret

run2:
jb 0dh,r2ed
setb 0dh
jb p3.1,r3ed
jb p3.0,r3ed

inc 41h
inc 41h
mov 5dh ,#2  ;发声
mov a,#10
cjne a,43h,$+3
jc r2ed
inc 41h
r2ed:ret

run3:
jb 0bh,r3ed
setb 0bh
jb p3.2,r3ed
jb p3.3,r3ed
inc 42h
inc 42h
mov 5dh ,#4  ;发声

mov a,#10
cjne a,43h,$+3
jc r3ed
inc 42h
r3ed:ret





t1int:jmp $
		mov th0,#(65535-1000)/255 
		mov tl0,#(65535-1000) 
		push acc
		push psw
		mov psw,#11000b
		mov a,p2          ;设p2.6/p2.7检测,r6记录123顺序,3dh记录上一次值,21h记录检测的桉键值
		anl a,#11000000b
ek0:	cjne a,#00000000b,ek2    ;检查出现在的状态
		cjne r6,#01000000b,ek1    ;查看上一次的状态
		call inc1
ek1:	cjne r6,#10000000b,ek2     ;查看上一次的状态
		call dec1
ek2:	cjne a,#01000000b,ek4    ;检查出现在的状态
		cjne r6,#11000000b,ek3    ;查看上一次的状态
		call inc1
ek3:	cjne r6,#00000000b,ek4     ;查看上一次的状态
		call dec1
ek4:	cjne a,#11000000b,ek6    ;检查出现在的状态
		cjne r6,#10000000b,ek5    ;查看上一次的状态
		call inc1
ek5:	cjne r6,#01000000b,ek6     ;查看上一次的状态
		call dec1
ek6:	cjne a,#10000000b,ek8    ;检查出现在的状态
		cjne r6,#00000000b,ek7    ;查看上一次的状态
		call inc1
ek7:	cjne r6,#11000000b,ek8     ;查看上一次的状态
		call dec1
ek8:	mov r6,a  ;将本次伯数据保存

		mov a,42h
		cjne a,#0,ek9
		setb p2.0
		jmp t0d
ek9:	cpl p2.0
		djnz 43h,t0d
		mov 43h,#100
		dec 42h
t0d:	pop psw
		pop acc
		reti



t0int:	push acc
	push psw
	cpl p2.6
	call su1
	pop psw
	pop acc
djnz 57h,t0end
djnz 56h,t0end


clr 0dh
clr 0bh

mov 56h,#20
clr 09h


djnz 55h,t0end
mov 55h,#20
jb 11h,t0int  ;高电平不允许计时
clr 0fh

t0end:	reti



su1:mov a,5dh      ;8音播放程序,58/59延时,59是0就停,5a分频系数,5b步数,5c分频,5d是N首两倍,是1停止,高频固定调用
    cjne a,#1,su6  ;查看1新声音标志,5e/5f为当前表,占用资源ACC/PSW/DPTR/58H-5AH
    mov a,59h
    cjne a,#0,su7  ;查看0声音结束标志,
    jmp su3
su2:mov a,5ah
    cjne a,#0,su4  ;查看是否需要静音
su3:setb p2.0
    ret
su4:djnz 5ch,su5   ;不需静音就分频发音
    mov 5ch,5ah
    cpl p2.0
su5:ret
su6:mov dptr,#sds  ;查表看该唱哪一首歌
    movc a,@a+dptr
    mov 5eh,a
    mov a,5dh
    inc a
    movc a,@a+dptr
    mov 5fh,a
    mov 5dh,#1     ;只查一次
    mov 5bh,#0     ;从该首头开始放
    jmp su8
su7:djnz 58h,su2   ;延时
    mov 58h,#200   ;延时
    djnz 59h,su2   ;发声时间减1到0后查下一步时间和音调
    inc 5bh
su8:mov a,5bh      ;发声的查表程序
    mov dph,5eh    ;装入当前首表地址
    mov dpl,5fh    ;装入当前首表地址
    movc a,@a+dptr ;查出当前步时间和音调,上半字节为时间0为结束,下半字节为音调D为静音
    mov 59h,a      ;发声时间,结束标志为0,最长时间为15个单位,
    anl a,#0fh     ;进一步查出音调,
    mov dptr,#sbb  ;查音阶分频表,
    movc a,@a+dptr
    mov 5ah,a      ;音调分频系数
    mov a,59h      ;再求出发生时间 
    anl a,#0f0h    ;删除音调数据
    ret     
saa:db 255,227,203, 191,170,152,143,128,114,101, 96,85,76,0;高频晶振音阶分频数据,音准高
sbb:db 101,90,  81, 76,  67, 60, 57, 51, 45, 40, 38,34,30,0;低频晶振音阶分频数据,音准较差
;sbb:db 10,9,  8, 7,  6, 5, 4, 3, 2, 1, 38,34,30,0;低频晶振音阶分频数据,音准较差
sds:db sd1/255,sd1,sd2/255,sd2,sd3/255,sd3,sd4/255,sd4,sd5/255,sd5,sd6/255,sd6,sd7/255,sd7,sd8/255,sd8
sd1:db 48h,0;声音数据:前面是时间,0结束,后面是音调,d静音.
sd2:db 1ch,1dh,1ch,0
sd3:db 18h,1dh,18h,1dh,1ch,0
sd4:db 1ch,1dh,1ch,1dh,1ch,1dh,1ch,1dh,1ch,0
sd5:db 1ch,15h,1dh,1ch,15h,0
sd6:db 1ch,15h,1dh,1ch,15h,0
sd7:db 4ch,4bh,4ah,49h,48h,47h,46h,45h,44h,43h,42h,41h,40h,0
sd8:db 40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4ah,4bh,4ch,0;8音程序结束



inc1:mov 02h,#0  ;模式为0
inc 39h
mov r4 ,39h
cjne r4,#0,iend
inc 38h
iend:ret


dec1:mov 02h,#0  ;模式为0
dec 39h
mov r4 ,39h
cjne r4,#255,dend
dec 38h
dend:ret 



d10ms:mov r7,#10
d1ms:djnz r6 ,$
djnz r7 ,d1ms
ret


js:
mov a,41h
mov b,#10
div ab
mov 30h,a
mov 31h,b 

mov a,30h
mov b,#10
div ab
mov 30h,b 



mov a,43h
mov b,#10
div ab
mov 32h,a
mov 33h,b 


mov a,32h
mov b,#10
div ab
mov 32h,b 


mov a,42h
mov b,#10
div ab
mov 34h,a
mov 35h,b 

mov a,34h
mov b,#10
div ab
mov 34h,b 

ret





disp:
djnz r7,$+4
mov r7,#6
mov a,r7
mov dptr,#tab1
movc a,@a+dptr
;mov p1,#0ffh
orl p1,#11111011b
;anl p2,#11000000b
anl a,#00111111b

;orl p2,a
;mov p2,a
mov a,r7
add a,#2fh
mov r0,a
mov a,@r0
mov dptr,#tab2
movc a,@a+dptr

mov c,p1.2
anl p1,a
mov p1.2,c
ret

tab1: db 11000000b,11000001b,11000010b,11000100b,11001000b,11010000b,11100000b
tab2: db 10000100b,11101110b,01000101b,01000110b,00101110b,00010110b,00010100b,11001110b,00000100b,00000110b,00001100b,00110100b,10010101b,01100100b,00010101b,00011101b,00000000b



ys00:djnz 50h,$
mov 50h,#10
djnz 51h, ys00

ret

TAB2b:   DB 11H,0D7H,32H,92H,0D4H,98H,18H,0D3H,10H,90H,50H,1CH,39H,16H,38H,78H,0ffH,0ffh,0ffh,0ffh


tab1b:db 10b,1b,100b,10000b,1000b,100000b,1000000b,10000000b;2a 1b 5c 7d 6e 3f 4g
;tab2:db 10000b,11011100b,101000b,01001000b,11000100b,01000010b,10b,11011000b,0b,1000000b,11111110b,9;2a 1b 5c 7d 6e 3f 4g

tab3:db 0001000b,1101110b,0010100b,0100100b,1100010b,0100001b,0000001b,1101100b,0000000b,0100000b,1111111b
tab4:db 00010001b,01111101b,00100011b,00101001b,01001101b,10001001b,10000001b,00111101b,00000001b,00001001b,11111111b


end 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -