环境描述,我们先在程序中运行了一个由时钟不断触发的中断(用于产生方波——实际是PWM波),此中断为低优先级,然后我们又设置了一个高优先级的按键中断,在中断退出前,我们对中断返回地址进行了重定向,可是返回后,经过了时钟初始化程序,时钟中断不再产生了。然后我们把按键中断优先级改为低级(就是把SETB PX0那句去掉),一切正常,不知何故?请高手指点迷津,非常感谢!!!!
;******************************************************************* ; 全国大学生电子设计大赛 ; (c)Copyright 2007-2008 Liu Cunxian ; All Rights Reserved ;文件名:ndcs.asm ;作 者:刘存显 ;功 能:数控直流电流源 ;*******************************************************************
ORG 0000H AJMP START ORG 0003H AJMP KEY ORG 000BH AJMP TIME0832 ORG 0013H AJMP A0809 ORG 0030H I EQU R6 ;电流标识(以实际的100倍标识)
;***********************主程序*************************** ;******************************************************** START: MOV SP,#5FH ;初始化堆栈
;0832初始化 MOV DPTR,#0BFFFH ;0832地址 MOV A,#00H MOVX @DPTR,A ;0832输出0V MOV I,#20 ;电流初始化,显示电流为0.2A ACALL DISPLAY ;显示
;开启中断 SETB EX1 SETB IT1 ;采用负跳变触发方式 SETB ET0 MOV TMOD,#01H ;定时/计数器0工作在方式一 SETB PX0 ;外部中断0设置为高优先级 SETB EA ;开启总中断
;********************A0809取样计算************************ ;******************************************************** ;0809取样 A0809_5: MOV DPTR,#0DFF8H ;0809首地址 SETB F0 ;标志第一次取样 MOV R1,#100 ;取样100次 A0809AD: MOVX @DPTR,A ;启动AD转换 A0809_4: CJNE R1,#0,A0809_4 ;R1为0时启动计算程序 AJMP JISUAN ;等待中断 ;0809中断响应--求平均 A0809: ; PUSH DEC R1 CLR C ;清空标志位 MOVX A,@DPTR ;读数 JZ CHU_SHI_HUA ;A为0则初始化 JBC F0,A0809_1 ;第一次取样 ADD A,R0 ;求和 RRC A ;取平均 ; CLR C A0809_1: MOV R0,A ;存数 CJNE R1,#0,A0809_2 ;相等时不再启动AD RETI
A0809_2: MOVX @DPTR,A ;启动AD转换 RETI ;计算--公式:Ton=I*92/R0-1 ;被除数:R2R3 ;商:R4R5 JISUAN: CLR C MOV R4,#0 ;商初始化 MOV R5,#0 MOV R1,#9 ;限定左移次数 MOV A,#92 MOV B,I MUL AB MOV R2,B ;存被除数 MOV R3,A SETB F0 ;标志第一次做除法
JISUAN2: JBC CY,JISUAN1 MOV A,R2 ;存被除数 MOV B,R0 ;除数 DIV AB JZ RL1 ;左移 MOV R2,B ;存被除数 JBC F0,JISUAN3 ;第一次做除法 INC R5 ;商加一
RL1: DEC R1 MOV A,R1 JZ JISUAN_END MOV A,R5 RLC A MOV R5,A MOV A,R4 RLC A MOV R4,A MOV A,R3 RLC A MOV R3,A MOV A,R2 RLC A MOV R2,A AJMP JISUAN2
JISUAN1: INC R5 SUBB A,R0 CLR C MOV R2,A AJMP RL1 JISUAN3: MOV R5,A ;存商 AJMP RL1 JISUAN_END: MOV A,R5 SUBB A,#1 MOV R5,A MOV A,R4 SUBB A,#0 MOV R4,A CLR EX1
;******************A0832PWM波初始化程序******************* ;******************************************************** A0832: CLR C MOV A,#0 ;计算定时器初值 SUBB A,R5 MOV R5,A CLR C MOV A,#255 SUBB A,R4 MOV R4,A CLR C MOV TL0,R5 ;计时器0定时时间设定 MOV TH0,R4 SETB F0 ;Ton/Toff选择标志 SETB TR0 ;定时开始 MOV DPTR,#0BFFFH MOV A,#255 MOVX @DPTR,A ;输出高电平 ;************************A0809取样************************ ;******************************************************** A0809TEST: MOV DPTR,#0DFF8H ;A0809首地址 MOVX @DPTR,A ;启动AD转换
A0809TEST1: JBC IE1,A0809TEST2 ;查询方式检测中断标志位 AJMP A0809TEST1 ;循环等待
A0809TEST2: MOVX A,@DPTR ;取电压 JZ CHU_SHI_HUA ;A为0则初始化 AJMP A0809TEST
;***********************部分子程序*********************** ;********************************************************
;重新初始化程序 CHU_SHI_HUA: CLR EA CLR TR0 AJMP START DELAY: PUSH 07H PUSH 06H MOV R7,#250 D1: MOV R6,#2 D2: DJNZ R5,$ DJNZ R6,D2 DJNZ R7,D1 POP 06H POP 07H RET
;********************键盘中断响应************************ ;******************************************************** KEY: PUSH 04H PUSH 05H PUSH PSW PUSH ACC MOV R4,#0 MOV A,P1 CPL A ANL A,#07H JZ KEYEND2 MOV R5,#10 ;延迟10ms ACALL DELAY MOV A,P1 CPL A ANL A,#07H JZ KEYEND2 JB ACC.0,DOWN JB ACC.1,UP JB ACC.2,RESET AJMP KEYEND2
;按键DOWN DOWN: ACALL KEYCHECK JZ DOWN1 ;当按键不满1s时运行 CJNE R4,#200,DOWN ;按键时间超过1s顺序执行
DOWN2: DEC I ;电流减一 ACALL KEY1 ;程序段复用 CJNE I,#20,DOWN2 ;循环减一直到I=20 DOWN3: ACALL KEYUP ;等待按键释放 JZ KEYEND AJMP DOWN3
DOWN1: CJNE I,#20,DOWN1_1 AJMP KEYEND
DOWN1_1: DEC I ;电流减一 ACALL DISPLAY AJMP KEYEND
;按键UP UP: ACALL KEYCHECK JZ UP1 ;当按键不满1s时运行 CJNE R4,#200,UP ;按键时间超过1s顺序执行
UP2: INC I ;电流加一 ACALL KEY1 ;程序段复用 CJNE I,#200,UP2 ;循环加一直到I=200 UP3: ACALL KEYUP ;等待按键释放 JZ KEYEND AJMP UP3
UP1: CJNE I,#200,UP1_1 AJMP KEYEND
UP1_1: INC I ;电流加一 ACALL DISPLAY AJMP KEYEND
;RESET键的算法不知道有没有人有更好的方法?????????????????????????????? ;按键RESET RESET: MOV SP,#5FH MOV DPTR,#CHU_SHI_HUA PUSH DPL PUSH DPH AJMP KEYEND1
;按键子程序 KEYEND2: POP ACC POP PSW POP 05H POP 04H RETI
KEYCHECK: MOV R5,#5 ;延迟5ms ACALL DELAY MOV A,P1 CPL A ANL A,#07H INC R4 RET KEY1: ACALL DISPLAY ACALL KEYUP ;检测按键释放 JZ KEYEND RET
KEYUP: MOV A,P1 CPL A ANL A,#07H RET KEYEND: MOV SP,#5FH MOV DPTR,#JISUAN ;PC值是16位的,#JISUAN应该也是16位的,不应该用A?????????????????????????????????????????????????? PUSH DPL PUSH DPH
KEYEND1: CLR TR0 CLR EX0 RETI
;********************A0832中断响应程序******************** ;******************************************************** TIME0832: CLR EX0 ;关闭外部中断0 PUSH DPL ;保存状态值 PUSH DPH PUSH ACC MOV DPTR,#0BFFFH JBC F0,Toff MOV TL0,R5 ;计时器0定时时间设定 MOV TH0,R4 MOV A,#255 MOVX @DPTR,A CPL F0 ;取反 AJMP TIME0832END Toff: MOV TL0,#156 ;计时器0定时时间设定 MOV TH0,#0FFH MOV A,#0 MOVX @DPTR,A
TIME0832END: POP ACC ;恢复状态值 POP DPH POP DPL SETB EX0 ;允许外部中断0 RETI
;***********************显示部分************************* ;******************************************************** DISPLAY: PUSH PSW ;保护数据 PUSH DPL PUSH DPH PUSH ACC PUSH B PUSH 00H PUSH 01H MOV DPTR,#TAB MOV A,I MOV R0,#30H ;初始化显示缓冲区 MOV R1,#3 ;显示位数
DISPLAY1: ;BCD码的转化与存储 INC R0 MOV B,#10 DIV AB MOV @R0,B DJNZ R1,DISPLAY1
DISPLAY2: MOV R0,#30H ;显示缓冲 MOV R1,#3 ;三个字
DISPLAY3: INC R0 ;地址加一 MOV A,@R0 MOVC A,@A+DPTR MOV SBUF,A ;显示输出 ACALL CHECK ;输出完毕 DJNZ R1,DISPLAY3 ;三个字 POP 01H ;退出保护 POP 00H POP B POP ACC POP DPH POP DPL POP PSW RET
CHECK: JNB TI,CHECK ;检测是否发送完毕 CLR TI RET
TAB: ;字模表 DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END ;本程序由xwj设计的UltraEdit脚本加亮显示,如需要脚本请访问我的Blog或联系xwjfile@21cn.com |