1. 有时会出现程序一点错误也没有,但就是不能正常运行的现象,最后我们发行是因为程序中有的指令书写得不规范导致的,例如有的 RET 返回指令一定要按正确格式书写或在两 行指令间最好不要留空行。
2. 程序中的跳转指令的运用很重要,为保险起见,都用 LJMP,我们就遇到过跳转指令用错 程序无法正常运行的现象。当用 JNZ 指令时,跳转范围比较少,这时要用一个标号中转。
3. 编程时要注意,在程序开始时,要写入各定时器中断的入口地址。
4. 编程过程中要注意加注释或分割线,否则,在程序过长时容易变得很乱,不便于查找或更改。
5. 程序的结构要设计的合理,避免上下乱调用的现象,这样会使程序更加清晰化。
6. 编程前要加流程图, 这样会使思路清晰, 例如数字音乐盒的设计思路完全可以按着 MP3 的工作方式列写流程图。
7. LCD 计时正常显示的解决办法:
a. 两个定时器同时工作,存在中断时序问题,刚开始时我们把定时器 1 设定在方式 3,计 250us,由于定时中断过于频繁,使 CPU 负载过大,导致音乐不能正常播放,时间不能正常 显示。解决办法:将定时器 1 设定在工作方式 1,16 位计数,计 50ms,效果有很大改观。但还有问题。
b. 当音乐为全 4 拍起始时,此时音乐节奏与定时器 T1 中断频率错开,LCD 显示和音乐播 放都会好一些。
c. 另外,在歌曲中,当遇到一个音符发音为 4 拍,在编曲中为*CH,托因时间较长,当定 时器 T1 此时来中断时,就会对歌曲播放产生影响,若改为发音一拍,中断对歌曲播放影响 减弱,但音乐效果变差。
d. 改进方案:若采用可以定时时间更长的单片机,可以避免所有问题。
单片机源程序(汇编语言):
- RS BIT P2.0 ;引脚定义,定义液晶显示端口标号
- RW BIT P2.1
- E BIT P2.2
- L50MS EQU 60H ;工作内存定义
- L1MS EQU 61H
- L250MS EQU 62H
- SEC EQU 65H
- MIN EQU 64H
- HOU EQU 63H
- ORG 0000H
- LJMP MAIN
- ORG 000BH ;定时器T0溢出中断入口地址
- LJMP TT0
- ORG 001BH ; 定时器T1溢出中断入口地址
- LJMP T1INT
- ORG 1000H
- MAIN: ;液晶初始化
- MOV SP,#70H
- MOV P0,#01H ;清屏
- CALL DISPLAY
- MOV P0,#38H ;8位,2行显示
- LCALL DISPLAY
- MOV P0,#0FH ;屏显on,光标on,闪烁on
- LCALL DISPLAY
- MOV P0,#06H ;计数地址加1,显示幕on
- LCALL DISPLAY
- LCALL INITIL ;内存初始化
- WAIT: LCALL KEY ;键盘扫描,是否有键按下,否则等待
- LCALL MODD
- LJMP WAIT
- KEY: NOP
- NOP
- LCALL KS
- JNZ K1 ;有按键转到K1
- LCALL KAIJI
- LCALL SOP
- XN: LJMP KEY
- K1: LCALL MODD
- LCALL MODD
- LCALL KS
- JNZ K2
- LJMP KEY
- K2: MOV R2,#0FEH ;读键盘
- MOV R4,#00H
- K3: MOV A,R2
- MOV P1,A
- MOV A,P1
- JB ACC.4,L1 ;为1跳转,第一行无按键
- MOV A,#00H
- LJMP LK
- L1: JB ACC.5,L2
- MOV A,#04H
- LJMP LK
- L2: JB ACC.6,L3
- MOV A,#08H
- LJMP LK
- L3: JB ACC.7,NEXT1
- MOV A,#0CH
- LK: ADD A,R4
- PUSH ACC
- K4: LCALL DELAY1 ;若同时有其他按键,则等待
- LCALL KS
- JNZ K4
- MOV R3,#07H
- CLR A
- MOV R0,#30H
- MOV R1,#31H
- MM1: MOV A,@R1
- MOV @R0,A
- INC R0
- INC R1
- DJNZ R3,MM1
- POP ACC
- MOV @R0,A
- RET
- NEXT1: INC R4 ;列扫描
- MOV A,R2
- JNB ACC.3,N2
- LJMP N1
- N2: LJMP KEY
- N1: RL A
- MOV R2,A
- LJMP K3
- KS: MOV A,#0F0H ;判断P1口
- MOV P1,A
- NOP
- NOP
- MOV A,P1
- CPL A
- ANL A,#0F0H
- RET
- DELAY1:SETB RS0
- DL: MOV R5,#0AH
- DL2: MOV R6,#63
- DL3: NOP
- NOP
- DJNZ R6,DL3
- DJNZ R5,DL2
- CLR RS0
- RET
- INITIL: ;30H-37H初值为零
- MOV R3,#08H
- MOV R0,#30H
- M1: MOV @R0,#00H
- INC R0
- DJNZ R3,M1
- RET
- MODD: ;显示
- MOV P0,#8EH
- CALL DISPLAY
- MOV A,37H
- MOV DPTR,#TABLE3
- MOVC A,@A+DPTR
- CALL WRITE2
- RET
- KAIJI: MOV A,37H ;开机提示字
- CJNE A,#0FH,DFF
- MOV P0,#80H ;设光标地址
- CALL DISPLAY
- MOV DPTR,#TABLE1;写数据
- CALL WRITE1
- DFF: RET
- ;按键值播放歌曲
- SOP: MOV A,37H
- CJNE A,#01H,A11
- LCALL MODD
- MOV 52H,#HIGH TABLE10
- MOV 53H,#LOW TABLE10
- LCALL INITILE2
- LCALL MAIN0
- A11: CJNE A,#02H,A22
- LCALL MODD
- MOV 52H,#HIGH TABLE20
- MOV 53H,#LOW TABLE20
- LCALL INITILE2
- lcall MAIN0
- A22: CJNE A,#03H,A33
- LCALL MODD
- MOV 52H,#HIGH TABLE30
- MOV 53H,#LOW TABLE30
- LCALL INITILE2
- lcall MAIN0
- A33: CJNE A,#04H,A44
- LCALL MODD
- MOV 52H,#HIGH TABLE40
- MOV 53H,#LOW TABLE40
- LCALL INITILE2
- lcall MAIN0
- A44: CJNE A,#05H,A55
- LCALL MODD
- MOV 52H,#HIGH TABLE50
- MOV 53H,#LOW TABLE50
- LCALL INITILE2
- lcall MAIN0
- A55: CJNE A,#06H,A66
- LCALL MODD
- MOV 52H,#HIGH TABLE60
- MOV 53H,#LOW TABLE60
- LCALL INITILE2
- lcall MAIN0
- A66: CJNE A,#07H,A77
- LCALL MODD
- MOV 52H,#HIGH TABLE70
- MOV 53H,#LOW TABLE70
- LCALL INITILE2
- lcall MAIN0
- A77: CJNE A,#08H,A88
- LCALL MODD
- MOV 52H,#HIGH TABLE80
- MOV 53H,#LOW TABLE80
- LCALL INITILE2
- lcall MAIN0
- A88: CJNE A,#09H,A99
- LCALL MODD
- MOV 52H,#HIGH TABLE90
- MOV 53H,#LOW TABLE90
- LCALL INITILE2
- lcall MAIN0
- A99: CJNE A,#0AH,AAA
- LCALL MODD
- MOV 52H,#HIGH TABLE100
- MOV 53H,#LOW TABLE100
- LCALL INITILE2
- lcall MAIN0
- AAA: RET
- INITILE2:
- MOV L50MS,#20
- MOV L1MS,#00H
- MOV L250MS,#00H
- MOV SEC,#00H
- MOV MIN,#00H
- MOV HOU,#00H
- MOV A,HOU
- MOV B,#10
- DIV AB
- ADD A,#30H ;将BCD吗转化为ASIIC码
- MOV P0,#0C8H ;显示小时十位
- CALL DISPLAY
- CALL WRITE2
- MOV A,B
- ADD A,#30H
- MOV P0,#0C9H ;显示小时个位
- CALL DISPLAY
- CALL WRITE2
- MOV A,#3AH
- MOV P0,#0DH ;显示冒号
- CALL DISPLAY
- CALL WRITE2
- MOV A,MIN
- MOV B,#10
- DIV AB
- ADD A,#30H
- MOV P0,#0CBH ;显示分十位
- CALL DISPLAY
- CALL WRITE2
- MOV A,B
- ADD A,#30H
- MOV P0,#0CCH ;显示分个位
- CALL DISPLAY
- CALL WRITE2
- MOV A,#3AH
- MOV P0,#0CDH ;显示冒号
- CALL DISPLAY
- CALL WRITE2
- MOV A,SEC
- MOV B,#10
- DIV AB
- ADD A,#30H
- MOV P0,#0CEH ;显示秒十位
- CALL DISPLAY
- CALL WRITE2
- MOV A,B
- ADD A,#30H
- MOV P0,#0CFH ;显示秒个位
- CALL DISPLAY
- CALL WRITE2
- MOV P0,#0C0H ;设光标地址
- CALL DISPLAY
- MOV DPTR,#TABLE2;写数据
- CALL WRITE1
- RET
- DISPLAY: CLR RS ;写指令
- CLR RW
- CLR E
- LCALL DELAY
- SETB E
- RET
- WRITE1: MOV R1,#00H ;写数据
- A1: MOV A,R1
- MOVC A,@A+DPTR
- CALL WRITE2
- INC R1
- CJNE A,#0FEH,A1 ;未到字符串末尾继续
- RET
- WRITE2: MOV P0,A
- SETB RS
- CLR RW
- CLR E
- CALL DELAY
- SETB E
- RET
- DELAY: MOV R4,#05
- D1: MOV R5,#0FFH
- DJNZ R5,$
- DJNZ R4,D1
- RET
- TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H
- DB 80H,90H,88H,83H,0C6H,0A1H,86H,8EH
- TAB1: DB 89H,86H,0C7H,0C7H,0C0H
- TAB2: DB 0C6H,88H,0C0H
- TABLE1: DB 'WELCOM HERE',0FEH
- TABLE2: DB 'DFF WB ',0FEH
- TABLE4: DB 'CAU',0FEH
- TABLE3: DB 30H,31H,32H,33h
- DB 34H,35H,36H,37H
- DB 38h,39H,41H,42H
- DB 43H,44H,45H,46H
- MAIN0: MOV TMOD,#11H ;播放歌曲程序
- MOV IE,#8aH
- MOV TH1, #3cH
- MOV TL1, #0b0H
- LCALL KS
- JNZ TTM12
- MOV 40H,#00H
- NEXT20: MOV A,40H
- MOV DPH,52H
- MOV DPL,53H
- MOVC A,@A+DPTR
- MOV R2,A
- JZ STOP
- ANL A,#0FH
- MOV R1,A
- MOV A,R2
- SWAP A
- ANL A,#0FH
- JNZ SING
- CLR TR0
- JMP W1
- SING: DEC A
- MOV 22H,A
- RL A
- MOV DPTR,#TABLE00
- MOVC A,@A+DPTR
- MOV TH0,A
- MOV 21H,A
- MOV A,22H
- RL A
- INC A
- MOVC A,@A+DPTR
- MOV TL0,A
- MOV 20H,A
- SETB TR0
- SETB TR1
- W1: LCALL DELAY30
- INC 40H
- LCALL KS ;有键跳出
- JNZ STOP
- LJMP NEXT20
- STOP: CLR TR0
- CLR TR1
- LJMP MAIN0
- TTM12: LCALL K2
- MOV A,37H
- CJNE A,#0EH,TTM13
- CLR TR1
- LCALL DELAY1
- TTM120: LCALL KS
- LCALL DELAY1
- JZ TTM120
- LCALL K2
- MOV A,37H
- CJNE A,#0EH,TTM120
- SETB TR1
- LJMP NEXT20
- TTM13: CJNE A,#0CH,TTM14
- MOV A,52H
- INC A
- MOV 52H,A
- MOV A,53H
- INC A
- MOV 53H,A
- MOV A,36H
- INC A
- MOV 37H,A
- LJMP TTM2
- TTM14: CJNE A,#0DH,TTM2
- MOV A,52H
- DEC A
- MOV 52H,A
- MOV A,53H
- DEC A
- MOV 53H,A
- MOV A,36H
- DEC A
- MOV 37H,A
- TTM2: RET
- TT0: PUSH ACC ;定时器中断子程序0
- PUSH PSW
- MOV TL0,20H
- MOV TH0,21H
- CPL P3.7
- POP PSW
- POP ACC
- RETI
- ;定时器中断子程序1
- T1INT: MOV TH1, #3CH ;定时器中断子程序1
- MOV TL1, #0B0H
- DJNZ L50MS,X4
- MOV L50MS,#20
- SECSET: ;每秒种时钟刷新秒显示一次
- MOV A,SEC
- MOV B,#10
- DIV AB
- ADD A,#30H
- MOV P0,#0CEH ;显示秒十位
- CALL DISPLAY
- CALL WRITE2
- MOV A,B
- ADD A,#30H
- MOV P0,#0CFH ;显示秒个位
- CALL DISPLAY
- CALL WRITE2
- MOV A,SEC
- INC A
- MOV SEC,A
- XRL A,#60
- X4: JNZ OUT
- MINSET: MOV SEC,#00H ; *每分钟刷新分显示一次
- MOV A,MIN
- INC A
- MOV MIN,A
- MOV B,#10
- DIV AB
- ADD A,#30H
- MOV P0,#0CBH ;显示分十位
- CALL DISPLAY
- CALL WRITE2
- MOV A,B
- ADD A,#30H
- MOV P0,#0CCH ;显示分个位
- CALL DISPLAY
- CALL WRITE2
- MOV A,MIN
- MOV B,#3
- MUL AB
- MOV B,#100
- DIV AB
- MOV R2,A
- MOV A,#10
- XCH A,B
- DIV AB
- MOV A,MIN
- XRL A,#60
- JNZ OUT
- HOUSET:
- MOV MIN,#00H ;每小时刷新小时显示一次
- MOV A,HOU
- MOV B,#10
- DIV AB
- ADD A,#30H ;将BCD吗转化为ASIIC码
- MOV P0,#0C8H ;显示小时十位
- CALL DISPLAY
- CALL WRITE2
- MOV A,B
- ADD A,#30H
- MOV P0,#0C9H ;显示小时个位
- CALL DISPLAY
- CALL WRITE2
- MOV A,HOU
- INC A
- MOV HOU,A
- XRL A,#10
- JNZ OUT
- SJMP OVERFLOW
- OUT: RETI;溢出处理
- OVERFLOW:
- MOV L50MS,#20
- MOV L1MS,#00H
- MOV L250MS,#00H
- MOV SEC,#00H
- MOV MIN,#00H
- MOV HOU,#00H
- RETI
- DELAY30:
- MOV R7,#2
- W2: MOV R4,#125
- W3: MOV R3,#248
- DJNZ R3,$
- DJNZ R4,W3
- DJNZ R7,W2
- DJNZ R1,DELAY30
- RET
- TABLE00:
- DW 64580,64684,64777,64820
- DW 64898,64968,65030,64260
- DW 64400,64524,65058,63835,64021
- TABLE10: ;第一首《精忠报国》
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
资料下载:
音乐盒.zip
(62.11 KB, 下载次数: 99)
|