单片机,双位数码管“一直”动态扫描显示R0数值,通过定时器T1定时1秒,使R0自减,写倒计时的汇编程序

单片机,要在双位数码管上显示R0的值,R0的值通过P0端口经过74LS47译码器送显,采用动态扫描的方式。定时器T1定时1秒,使R0自减,在数码管上就能显示倒计时的效果。用汇编语言,问题是如果一方面一直扫描P0端口(动态扫描是要循环的吧),同时又要让定时器T1工作,1秒时间到使R0减1,这两个部分怎么同时表达,汇编语言是逐条执行啊,下面程序中 根本不能进入定时器T1程序 ,只显示初始值20
;****************************************************************
ORG 0000H
LJMP MAIN
ORG 001BH ;定时器1入口地址
LJMP TIMER1
ORG 0100H

MAIN:MOV R2,#20 ;R2的值可以随时修改

DISP: MOV 01H,R2 ;南北方向显示初值R2=20秒
MOV R0,01H
MOV A,R0
MOV B,#10
DIV AB
MOV P0,A ;段选
MOV P2,#01 ;位选
ACALL D1ms ;延时
MOV P2,#00 ;清零
MOV P0,B
MOV P2,#02
ACALL D1ms
MOV P2,#00 ;清零

LJMP DISP ;这个地方就一直循环,怎样实现定时器的作用??
;*********** 定 时 1 秒 中 断 ***********
TIMER:
SETB EA ;开中断
SETB ET1 ;打开定时器1中断

MOV TMOD,#10H ;T1模式1(十六位定时器)
MOV TH1,#0D8H ;赋初值,定时10毫秒
MOV TL1,#0F0H
SETB TR1 ;启动T1

MOV R5,#64H ;循环100次

LP1: JNB TF1,$ ;TF1=0,等待,没有溢出
CLR TF1
LJMP LP2
LP2:
MOV TH1,#0D8H ;重新赋初值
MOV TL1,#0F0H
DJNZ R5,LP1 ;100次循环

SJMP TIMER

TIMER1:DEC R2 ; 定时1秒执行程序 南北方向倒计时减1
RETI
;************ 延 时 D1ms 程序***********
D1ms:
MOV R7,#02H
DL: MOV R6,#0FFH
DL1:DJNZ R6,DL1
DJNZ R7,DL
RET
;***************************************
END
如果是用 C语言 会不会有这个问题??

使用中断就行了啊,C语言也是这样的,编译器会把C语言转换成汇编语言。然后再转换成HEX文件。下面是在你的程序上修改的,没试过,你编译一下看看有没错误
ORG 00H
LJMP MAIN
ORG 001BH ;定时器1入口地址
LJMP TIMER1_ISR
ORG 0100H

MAIN:
MOV TMOD,#10H
MOV TL1,#0F0H
MOV TH1,#0D8H ;赋初值,定时10毫秒
SETB TR1
MOV IE,#88H
MOV R2,#20 ;R2的值可以随时修改
MOV R3,#100 ;100 * 10MS = 1S

DISP:
MOV A,R2 ;南北方向显示初值R2=20秒
MOV B,#10
DIV AB
MOV P0,A ;段选
MOV P2,#01 ;位选
ACALL D1ms ;延时
MOV P2,#00 ;清零
MOV P0,B
MOV P2,#02
ACALL D1ms
MOV P2,#00 ;清零
LJMP DISP ;这个地方就一直循环,怎样实现定时器的作用??
;*********** 定 时 1 秒 中 断 ***********
TIMER1_ISR:
MOV TL1,#0F0H
MOV TH1,#0D8H ;赋初值,定时10毫秒
PUSH ACC
PUSH PSW
DJNZ R3,TIMER1_END
MOV R3,#100
MOV A,R2
DEC R2
JNZ TIMER1_END
MOV R2,#20
TIMER1_END:
POP PSW
POP ACC
RETI
;************ 延 时 D1ms 程序***********
D1ms:
MOV R7,#02H
DL:
MOV R6,#0FFH
DL1:
DJNZ R6,DL1
DJNZ R7,DL
RET
;***************************************
END追问

你那个入栈和出栈的语句有什么作用??我去掉之后执行效果一样

追答

那是保存ACC和PSW的内容,因为中断程序使用了ACC,语句MOV A,R2会影响PSW的奇偶标志位
,而中断发生的时候主程序可能正在使用ACC寄存器,或者判断PSW的奇偶标志位,所以需要保存。当然你这个程序是没有用到奇偶标志位的,不过ACC是使用到的。
MOV B,#10
DIV AB例如程序在这里产生中断,如果中断程序中没有保存ACC,且正好R3减1为零
DJNZ R3,TIMER1_END
MOV R3,#100
MOV A,R2那么这条语句在中断程序中将被执行,返回的时候ACC的值将会等于R2
那么主程序中的语句MOV P0,A ;就不会得到你想要的结果了。
你去掉之后效果一样,是因为程序没有正好在那两条语句中产生中断,或者即使在那两条语句中产生中断,但R3-1不为零。所以效果是一样的,但不保证每次都能这样。所以要保证程序能长期正常运行,那几条语句是必不可少的。至少ACC的压栈/出栈在你的程序中不能省略

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-03-25
单片机中,C语言和汇编语言是一样的,都可以运行。
定时计数器1,只要TR1=1,就开始计数或定时
程序在DISP和LJMP DISP之间不断循环,但是如果开了中断,定时器溢出的时候就会进入中断子程序。
你主程序里少了对计数器的设置。追问

确实是。还在修改

第2个回答  2014-03-25
5+59+58d+9a59+9+468
第3个回答  2014-03-25
阿达撒的飞飞飞去玩