好厉害,都没写过这么长的汇编。 |
双卡录放机,组合音响等都落寞了。拿来练练手还是不错的 |
你好,还有没有搞单片机控制录音机芯,想跟你学习学习。 |
终于弄明白了,是因为这里使用的是LCALL指令但指令出去后的子程序都没有RET返回所以就跑飞了 LCALL DISP ;调用显示及功能操作 LJMP L1 ;返回做下一次扫描 ....... DISP: MOV DPTR, #TABKEY ;读功能操作数据 MOV A,R1 MOV B,#3 MUL AB JMP @A+DPTR ;转执行具体功能操作 |
比如你在死等硬件某个信号,程序的这种写法是有风险的,一但硬件有问题(你等不到),就死在那里了。 你也可以走全速仿真,在你认为“已死机”的时候,断下来,看看这时的PC指针指向何处,再对照你的程序地址,以找到死在何处?或是飞出程序之外了。 |
yzwzfyz 发表于 2018-12-15 12:29 谢谢。复杂程序或许C比较好应付,我刚学汇编个把月。感觉指向明确,当然在有注释的情况下还是好理解的。今后是要养成画流程图的习惯。不过,《超时跳出》,我都是设定跳回矩阵键盘检测那去的呀,因为感觉所有控制都是根据矩阵键盘的键值进行操作的。比如说按下播放键执行完毕程序就回到矩阵键盘检测去了。还是会死机。特别是反复的按前进,后退,播放最容易死机,1602屏是一片乱码。怎么回事呢?真的搞不懂 |
不错!汝子可教也! 画出程序架构的逻辑框图。看看框图中有没有死循环结构。设法拆开它(超时跳出)。 这个程序还不复杂,如果再复杂几十倍,当如何处理呢? 所以必须学会画程序流程图,并以流程图审核程序。 |
抱歉,第一次发帖,有重复了,烦请版主帮忙把我发的后面几个贴删除了吧。谢谢 |
我现在用的是广电网络,龟速。没办法 |
汇编程序: ORG 0040H CLR EA ;关闭所有中断 ;----------------定义1602显示屏端口----------- RS EQU P3.0 ;数据/命令选择 RW EQU P3.1 ;读/写选择 E EQU P3.2 ;使能控制 COUNT EQU 30H ;字数计数 DISPAD EQU 31H ;显示起始地址 ;---------------定义机芯控制端口-------------- AHD EQU P1.0 ; A带仓检测口 LYJ EQU P1.1 ; 录音使能检测 BHD EQU P1.2 ; B带仓检测口 BMC EQU P1.3 ; B仓脉冲检测 AMC EQU P1.4 ; A仓脉冲检测 BCT EQU P1.5 ; B仓机芯动作控制 MDZ EQU P1.6 ; 马达控制 ACT EQU P1.7 ; A仓机芯动作控制 AKEY DATA 32H ;保存A仓键值 BKEY DATA 33H ;保存B仓键值 ;---------------1602显示初始化------------ MOV P0,#01H ;清屏并光标复位 ACALL ENABLE ;调用写入命令子程序 MOV P0,#38H ;设置显示模式:8位2行5x7点阵 ACALL ENABLE ;调用写入命令子程序 MOV P0,#0CH ;显示器开、光标关、光标不闪烁 ACALL ENABLE ;调用写入命令子程序 MOV P0,#06H ;文字不动,光标自动右移 ACALL ENABLE ;调用写入命令子程序 LJMP START ;--------------- 数据写入---------------- QUSHU: CLR A MOVC A,@A+DPTR ;查表 MOV P0,A SETB RS ;RS=1 CLR RW ;RW=0 ;准备写入数据 CLR E ;E=0 ;执行显示命令 LCALL DELAY ;判断液晶模块是否忙? INC DPTR DJNZ COUNT,QUSHU RET ;--------------- 命令写入---------------- ENABLE: CLR RS CLR RW CLR E LCALL DELAY SETB E RET ;--------------- 判断忙---------------- DELAY: MOV P0,#0FFH CLR RS SETB RW CLR E NOP SETB E JB P0.7,DELAY ;P1.7为高电平表示忙循环等待 RET ;------------- 开始程序 ---------------- START: MOV P0,#080H ;第1行第1位 LCALL ENABLE ;调用写入命令子程序 MOV DPTR,#TAB0 ;显示 A: B: MOV COUNT,#0AH ;显示10个字符。 LCALL QUSHU MOV AKEY,#00H MOV BKEY,#00H MOV R4, #00H ;------------ 键检测 -------------------- L1: LCALL CDJC ;盒带状况显示 LCALL MCXHJC ;脉冲信号检测 LCALL YXZKXS ;运行状况显示 MOV R3, #0F7H MOV R1, #00H ;初始化 L2: MOV A, R3 MOV P2, A ;R3值赋P2口 MOV A, P2 ;读取键值 MOV R4, A SETB C ;设CY=1 MOV R5, #04H ;扫描4次 L3: RLC A ;A带进位左移一位 JNC KEY ;CY=0,有键按下,转键处理 INC R1 ;无键按下,扫描下一列 DJNZ R5, L3 ;扫描不够4次,再扫描, MOV A, R3 SETB C ;设CY=1 RRC A ;右移一位, MOV R3, A JC L2 LJMP L1 ;重新扫描 KEY: LCALL DL30MS ;延时30Ms D1: MOV A, P2 XRL A,R4 JZ D1 ;等待键放开 LCALL BB ;按键提示声 MOV A, R1 LCALL DISP ;调用显示及功能操作 LJMP L1 ;返回做下一次扫描 ;********** BB提示声音 *********** BB: MOV R6,250 BB1: CLR P3.3 ACALL BB2 SETB P3.3 LCALL BB2 DJNZ R6,BB1 RET BB2: MOV R7,#50 DJNZ R7,$ RET ;************输出控制*************** DISP: MOV DPTR, #TABKEY ;读功能操作数据 MOV A,R1 MOV B,#3 MUL AB JMP @A+DPTR ;转执行具体功能操作 ;-------------盒带状况显示----------------- CDJC: JB AHD,AWHD MOV DISPAD,#083H ;A有盒带 MOV DPTR,#TAB2 ;显示 RADY LCALL DISP0 LJMP BHDJC AWHD: MOV DISPAD,#083H ;A无盒带 MOV DPTR,#TAB1 ;显示 -- LCALL DISP0 BHDJC: JB BHD,BWHD MOV DISPAD,#08BH ;B有盒带 MOV DPTR,#TAB2 ;显示 RADY LCALL DISP0 RET BWHD: MOV DISPAD,#08BH ;B无盒带 MOV DPTR,#TAB1 ;显示 -- DISP0: MOV P0,DISPAD LCALL ENABLE MOV COUNT,#04H LCALL QUSHU RET ;*************脉冲信号检测********** MCXHJC: MOV A,AKEY ;检测A键值 JZ BMCJC ;A仓无键按下检测B仓 JNB AMC,BMCJC ;有脉冲,检测B仓 LCALL S4 ;去A停止键 BMCJC: MOV A,BKEY ;检测B键值 JZ FHJPJC ;B仓无键按下返回 JNB BMC,FHJPJC ;有脉冲,返回 LCALL S12 ;去B停止键 FHJPJC: RET ;*************运行状况显示********** YXZKXS: MOV A,AKEY CJNE A,#00H, AXS1 MOV DISPAD,#0C2H MOV DPTR,#TAB3 ;A显示 STOP LCALL DISP0 LJMP BXS1 AXS1: CJNE A,#01H, AXS2 MOV DISPAD,#0C2H MOV DPTR,#TAB4 ;A显示 >> LCALL DISP0 LJMP BXS1 AXS2: CJNE A,#02H, AXS3 MOV DISPAD,#0C2H MOV DPTR,#TAB5 ;A显示 >>>> LCALL DISP0 LJMP BXS1 AXS3: CJNE A,#03H, BXS1 MOV DISPAD,#0C2H MOV DPTR,#TAB6 ;A显示 <<<< LCALL DISP0 BXS1: MOV A,BKEY CJNE A,#00H, BXS2 MOV DISPAD,#0CAH MOV DPTR,#TAB3 ;B显示 STOP LCALL DISP0 RET BXS2: CJNE A,#01H, BXS3 MOV DISPAD,#0CAH MOV DPTR,#TAB4 ;B显示 >> LCALL DISP0 RET BXS3: CJNE A,#02H, BXS4 MOV DISPAD,#0CAH MOV DPTR,#TAB5 ;B显示 >>>> LCALL DISP0 RET BXS4: CJNE A,#03H, XSFH MOV DISPAD,#0CAH MOV DPTR,#TAB6 ;B显示 <<<< LCALL DISP0 XSFH: RET ;************ A带 播放 ************** S1: JB AHD,AJX100 MOV A,AKEY ;读保存的键值 CJNE A,#01H,AJX101 ;此键未按过,检查其他键 AJX100: LJMP L1 ;正在执行此键操作,返回 AJX101: CJNE A,#00H,AJX102 ;有键按下(停止键除外) AJMP AJX103 AJX102: LCALL ATZ ;去停止键 AJX103: LCALL MDJC ;启动马达 CLR ACT LCALL DL350MS ;电磁铁吸合时间350MS SETB ACT MOV AKEY,#01H ;保存键值 LJMP L1 ;************** A带 快进 ************** S2: JB AHD,AJX200 MOV A,AKEY CJNE A,#02H,AJX201 AJX200: LJMP L1 AJX201: CJNE A,#00H,AJX202 AJMP AJX203 AJX202: LCALL ATZ AJX203: LCALL MDJC MOV R0,#2 ;电磁铁吸合两次 DE1: CLR ACT LCALL DL100MS SETB ACT LCALL DL200MS DJNZ R0,DE1 MOV AKEY,#02H LJMP L1 ;************* A带 快倒 *********** S3: JB AHD,AJX300 MOV A,AKEY CJNE A,#03H,AJX301 AJX300: LJMP L1 AJX301: CJNE A,#00H,AJX302 AJMP AJX303 AJX302: LCALL ATZ AJX303: LCALL MDJC CLR ACT LCALL DL100MS SETB ACT MOV AKEY,#03H LJMP L1 ;************* A带 停止 ************ S4: JNB AHD,AJX000 LJMP L1 ;A仓无带,返回 AJX000: MOV A,AKEY CJNE A,#00H,AJX001 ;有键按下 LJMP L1 AJX001: ACALL ATZ ;停止 MOV AKEY,#00H MOV A,BKEY CJNE A,#00H,AFH0 ;B仓运行中,返回 SETB MDZ ;马达停止 AFH0: LJMP L1 ATZ: CLR ACT LCALL DL50MS SETB ACT LCALL DL350MS SETB P3.4 ;录音停止 RET ;********** B带 播放 ************* S9: JNB BHD,BJX100 LJMP L1 BJX100: MOV A,BKEY CJNE A,#01H,BJX101 LJMP L1 BJX101: CJNE A,#00H,BJX102 AJMP BJX103 BJX102: LCALL BTZ BJX103:LCALL MDJC CLR BCT LCALL DL350MS SETB BCT MOV BKEY,#01H LJMP L1 ;********** B带 快进 ************ S10: JNB BHD,BJX200 LJMP L1 BJX200: MOV A,BKEY CJNE A,#02H,BJX201 LJMP L1 BJX201: CJNE A,#00H,BJX202 AJMP BJX203 BJX202: LCALL BTZ BJX203:LCALL MDJC MOV R0,#2 DE2: CLR BCT LCALL DL100MS SETB BCT LCALL DL200MS DJNZ R0,DE2 MOV BKEY,#02H LJMP L1 ;************ B带 快倒 ************ S11: JNB BHD,BJX300 LJMP L1 BJX300: MOV A,BKEY CJNE A,#03H,BJX301 LJMP L1 BJX301: CJNE A,#00H,BJX302 AJMP BJX303 BJX302: LCALL BTZ BJX303:LCALL MDJC CLR BCT LCALL DL100MS SETB BCT MOV BKEY,#03H LJMP L1 ;*********** B带 停止 ********** S12: JNB BHD,BJX000 LJMP L1 BJX000: MOV A,BKEY CJNE A,#00H,BJX002 LJMP L1 BJX002: ACALL BTZ MOV BKEY,#00H MOV A,#00H CJNE A,AKEY,BFH0 ;A仓运行中,返回 SETB MDZ ;马达停止 BFH0: LJMP L1 BTZ: CLR BCT LCALL DL50MS SETB BCT LCALL DL350MS RET ;--------------马达启动------------ MDJC: JNB MDZ,FHA ;马达已经运行 CLR MDZ ;启动马达 LCALL DL350MS ;延时待马达运行平稳 FHA: RET ;-------------- 录音 -------------- S16: JNB P3.4,LYJZ JB LYJ,LYJZ ;禁止录音 CLR P3.4 ;录音允许 LCALL S1 LYJZ: LJMP L1 ;------------ 暂无定功能 ---------- S5: LJMP L1 S6: LJMP L1 S7: LJMP L1 S8: LJMP L1 S13: LJMP L1 S14: LJMP L1 S15: LJMP L1 ;*********** 延时程序 ********** DL350MS: MOV R5,#35 ;延时350毫秒 ACALL DT1 RET DL200MS: MOV R5,#20 ;延时200毫秒 ACALL DT1 RET DL100MS: MOV R5,#10 ;延时100毫秒 ACALL DT1 RET DL50MS: MOV R5,#5 ;延时50毫秒 ACALL DT1 RET DL30MS: MOV R5,#3 ;延时30毫秒 DT1: MOV R6,#20 DT2: MOV R7,#250 DJNZ R7,$ DJNZ R6,DT2 DJNZ R5,DT1 RET ;***********控制跳转数据 *********** TABKEY: LJMP S1 ;A播放 LJMP S2 ;A快进 LJMP S3 ;A快倒 LJMP S4 ;A停止 LJMP S5 ; LJMP S6 ; LJMP S7 ; LJMP S8 ; LJMP S9 ;B播放 LJMP S10 ;B快进 LJMP S11 ;B快倒 LJMP S12 ;B停止 LJMP S13 LJMP S14 LJMP S15 LJMP S16 ;录音 TAB0: DB 'A: B:' TAB1: DB ' -- ' TAB2: DB 'RADY' TAB3: DB 'STOP' TAB4: DB ' >> ' TAB5: DB '>>>>' TAB6: DB '<<<<' END |