;;?AT89C2051時鐘程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;定時器T0、T1溢出周期為50MS,T0為秒計數用,?T1為調整時閃爍用,
;P3.7為調整按鈕,P1口?為字符輸出口,采用共陽顯示管。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?中斷入口程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG0000H?;程序執行開始地址
LJMPSTART;跳到標號START執行
ORG0003H?;外中斷0中斷程序入口
RETI;外中斷0中斷返回
ORG000BH?;定時器T0中斷程序入口
LJMPINTT0;跳至INTTO執行
ORG0013H?;外中斷1中斷程序入口
RETI;外中斷1中斷返回
ORG001BH?;定時器T1中斷程序入口
LJMPINTT1;跳至INTT1執行
ORG0023H?;串行中斷程序入口地址
RETI;串行中斷程序返回
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?主?程?序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START:MOVR0,#70H?;清70H-7AH共11個內存單元
MOVR7,#0BH
CLEARDISP:
MOV@R0,#00H
INCR0
DJNZR7,CLEARDISP
MOV20H,#00H?;清20H(標志用)
MOV7AH,#0AH?;放入"熄滅符"數據
MOVTMOD,#11H?;設T0、T1為16位定時器
MOVTL0,#0B0H?;50MS定時初值(T0計時用)
MOVTH0,#3CH?;50MS定時初值
MOVTL1,#0B0H?;50MS定時初值(T1閃爍定時用)
MOVTH1,#3CH?;50MS定時初值
SETBEA?;總中斷開放
SETBET0?;允許T0中斷
SETBTR0?;開啟T0定時器
MOVR4,#14H?;1秒定時用初值(50MS×20)
START1:LCALLDISPLAY;調用顯示子程序
JNBP3.7,SETMM1;P3.7口為0時轉時間調整程序
SJMPSTART1;P3.7口為1時跳回START1
SETMM1:LJMPSETMM;轉到時間調整程序SETMM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?1秒計時程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中斷服務程序
INTT0:PUSHACC?;累加器入棧保護
PUSHPSW?;狀態字入棧保護
CLRET0?;關T0中斷允許
CLRTR0?;關閉定時器T0
MOVA,#0B7H?;中斷響應時間同步修正
ADDA,TL0?;低8位初值修正
MOVTL0,A;重裝初值(低8位修正值)
MOVA,#3CH?;高8位初值修正
ADDCA,TH0
MOVTH0,A;重裝初值(高8位修正值)
SETBTR0?;開啟定時器T0
DJNZR4,OUTT0;20次中斷未到中斷退出
ADDSS:MOVR4,#14H?;20次中斷到(1秒)重賦初值
MOVR0,#71H?;指向秒計時單元(71H-72H)
ACALLADD1;調用加1程序(加1秒操作)
MOVA,R3;秒數據放入A(R3為2位十進制數組合)
CLRC;清進位標志
CJNEA,#60H,ADDMM
ADDMM:JCOUTT0;小于60秒時中斷退出
ACALLCLR0;大于或等于60秒時對秒計時單元清0
MOVR0,#77H?;指向分計時單元(76H-77H)
ACALLADD1;分計時單元加1分鐘
MOVA,R3;分數據放入A
CLRC;清進位標志
CJNEA,#60H,ADDHH
ADDHH:JCOUTT0;小于60分時中斷退出
ACALLCLR0;大于或等于60分時分計時單元清0
MOVR0,#79H?;指向小時計時單元(78H-79H)
ACALLADD1;小時計時單元加1小時
MOVA,R3;時數據放入A
CLRC;清進位標志
CJNEA,#24H,HOUR
HOUR:JCOUTT0;小于24小時中斷退出
ACALLCLR0;大于或等于24小時小時計時單元清0
OUTT0:MOV72H,76H?;中斷退出時將分、時計時單元數據移
MOV73H,77H?;入對應顯示單元
MOV74H,78H
MOV75H,79H
POPPSW?;恢復狀態字(出棧)
POPACC?;恢復累加器
SETBET0?;開放T0中斷
RETI;中斷返回
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?閃動調時?程?序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T1中斷服務程序,用作時間調整時調整單元閃爍指示
INTT1:PUSHACC?;中斷現場保護
PUSHPSW
MOVTL1,?#0B0H;裝定時器T1定時初值
MOVTH1,?#3CH
DJNZR2,INTT1OUT;0.3秒未到退出中斷(50MS中斷6次)
MOVR2,#06H?;重裝0.3秒定時用初值
CPL02H?;0.3秒定時到對閃爍標志取反
JB02H,FLASH1;02H位為1時顯示單元"熄滅"
MOV72H,76H?;02H位為0時正常顯示
MOV73H,77H
MOV74H,78H
MOV75H,79H
INTT1OUT:
POPPSW?;恢復現場
POPACC
RETI;中斷退出
FLASH1:JB01H,FLASH2;01H位為1時,轉小時熄滅控制
MOV72H,7AH?;01H位為0時,"熄滅符"數據放入分
MOV73H,7AH?;顯示單元(72H-73H),將不顯示分數據
MOV74H,78H
MOV75H,79H
AJMPINTT1OUT;轉中斷退出
FLASH2:MOV72H,76H?;01H位為1時,"熄滅符"數據放入小時
MOV73H,77H?;顯示單元(74H-75H),小時數據將不顯示
MOV74H,7AH
MOV75H,7AH
AJMPINTT1OUT;轉中斷退出
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?加1子?程?序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADD1:MOVA,@R0;取當前計時單元數據到A
DECR0;指向前一地址
SWAPA;A中數據高四位與低四位交換
ORLA,@R0;前一地址中數據放入A中低四位
ADDA,#01H?;A加1操作
DAA;十進制調整
MOVR3,A;移入R3寄存器
ANLA,#0FH?;高四位變0
MOV@R0,A;放回前一地址單元
MOVA,R3;取回R3中暫存數據
INCR0;指向當前地址單元
SWAPA;A中數據高四位與低四位交換
ANLA,#0FH?;高四位變0
MOV@R0,A;數據放入當削地址單元中
RET;子程序返回
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?清零程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;對計時單元復零用
CLR0:CLRA;清累加器
MOV@R0,A;清當前地址單元
DECR0;指向前一地址
MOV@R0,A;前一地址單元清0
RET;子程序返回
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?時鐘調整程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;當調時按鍵按下時進入此程序
SETMM:CLRET0?;關定時器T0中斷
CLRTR0?;關閉定時器T0
LCALLDL1S;調用1秒延時程序
JBP3.7,CLOSEDIS;鍵按下時間小于1秒,關閉顯示(省電)
MOVR2,#06H?;進入調時狀態,賦閃爍定時初值
SETBET1?;允許T1中斷
SETBTR1?;開啟定時器T1
SET2:JNBP3.7,SET1;P3.7口為0(鍵未釋放),等待
SETB00H?;鍵釋放,分調整閃爍標志置1
SET4:JBP3.7,SET3;等待鍵按下
LCALLDL05S;有鍵按下,延時0.5秒
JNBP3.7,SETHH;按下時間大于0.5秒轉調小時狀態
MOVR0,#77H?;按下時間小于0.5秒加1分鐘操作
LCALLADD1;調用加1子程序
MOVA,R3;取調整單元數據
CLRC;清進位標志
CJNEA,#60H,HHH;調整單元數據與60比較
HHH:JCSET4;調整單元數據小于60轉SET4循環
LCALLCLR0;調整單元數據大于或等于60時清0
CLRC;清進位標志
AJMPSET4;跳轉到SET4循環
CLOSEDIS:
SETBET0?;省電(LED不顯示)狀態。開T0中斷
SETBTR0?;開啟T0定時器(開時鐘)
CLOSE:JBP3.7,CLOSE;無按鍵按下,等待。
LCALLDISPLAY;有鍵按下,調顯示子程序延時削抖
JBP3.7,CLOSE;是干擾返回CLOSE等待
WAITH:JNBP3.7,WAITH;等待鍵釋放
LJMPSTART1;返回主程序(LED數據顯示亮)
SETHH:CLR00H?;分閃爍標志清除(進入調小時狀態)
SETHH1:JNBP3.7,SET5;等待鍵釋放
SETB01H?;小時調整標志置1
SET6:JBP3.7,SET7;等待按鍵按下
LCALLDL05S;有鍵按下延時0.5秒
JNBP3.7,SETOUT;按下時間大于0.5秒退出時間調整
MOVR0,#79H?;按下時間小于0.5秒加1小時操作
LCALLADD1;調加1子程序
MOVA,R3
CLRC
CJNEA,#24H,HOUU;計時單元數據與24比較
HOUU:JCSET6;小于24轉SET6循環
LCALLCLR0;大于或等于24時清0操作
AJMPSET6;跳轉到SET6循環
SETOUT:JNBP3.7,SETOUT1;調時退出程序。等待鍵釋放
LCALLDISPLAY;延時削抖
JNBP3.7,SETOUT;是抖動,返回SETOUT再等待
CLR01H?;清調小時標志
CLR00H?;清調分標志
CLR02H?;清閃爍標志
CLRTR1?;關閉定時器T1
CLRET1?;關定時器T1中斷
SETBTR0?;開啟定時器T0
SETBET0?;開定時器T0中斷(計時開始)
LJMPSTART1;跳回主程序
SET1:LCALLDISPLAY;鍵釋放等待時調用顯示程序(調分)
AJMPSET2;防止鍵按下時無時鐘顯示
SET3:LCALLDISPLAY;等待調分按鍵時時鐘顯示用
AJMPSET4
SET5:LCALLDISPLAY;鍵釋放等待時調用顯示程序(調小時)
AJMPSETHH1;防止鍵按下時無時鐘顯示
SET7:LCALLDISPLAY;等待調小時按鍵時時鐘顯示用
AJMPSET6
SETOUT1:LCALLDISPLAY;退出時鐘調整時鍵釋放等待
AJMPSETOUT;防止鍵按下時無時鐘顯示
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?顯示程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;顯示數據在70H-75H單元內,用六位LED共陽數碼管顯示,P1口輸出段碼數據,P3口作
;掃描控制,每個LED數碼管亮1MS時間再逐位循環。
DISPLAY:MOVR1,#70H?;指向顯示數據首址
MOVR5,#0FEH?;掃描控制字初值
PLAY:MOVA,R5;掃描字放入A
MOVP3,A;從P3口輸出
MOVA,@R1;取顯示數據到A
MOVDPTR,#TAB;取段碼表地址
MOVCA,@A+DPTR;查顯示數據對應段碼
MOVP1,A;段碼放入P1口
LCALLDL1MS;顯示1MS
INCR1;指向下一地址
MOVA,R5;掃描控制字放入A
JNBACC.5,ENDOUT;ACC.5=0時一次顯示結束
RLA;A中數據循環左移
MOVR5,A;放回R5內
AJMPPLAY;跳回PLAY循環
ENDOUT:SETBP3.5?;一次顯示結束,P3口復位
MOVP1,#0FFH?;P1口復位
RET;子程序返回
TAB:DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH
;共陽段碼表?"0""1""2"?"3""4""5""6""7"?"8""9""不亮"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;?延時程序?;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;1MS延時程序,LED顯示程序用
DL1MS:MOVR6,#14H
DL1:MOVR7,#19H
DL2:DJNZR7,DL2
DJNZR6,DL1
RET
;20MS延時程序,采用調用顯示子程序以改善LED的顯示閃爍現象
DS20MS:ACALLDISPLAY
ACALLDISPLAY
ACALLDISPLAY
RET
;延時程序,用作按鍵時間的長短判斷
DL1S:LCALLDL05S
LCALLDL05S
RET
DL05S:MOVR3,#20H?;8毫秒*32=0.196秒
DL05S1:LCALLDISPLAY
DJNZR3,DL05S1
RET
END