/*************************************************************************************** 008.ASM 用八位數碼管顯示時間,通過兩個按鍵改變顯示內容及修改時間 接線:J15.J16短接,P0接八位數碼管,P2接獨立鍵盤 2010.09.06 ***************************************************************************************/ ORG 0000H LJMP MAIN ORG 001BH LJMP INT_T1 ORG 0040H MAIN: LCALL FRIST ;上電初始化 LOOP: ;主循環 LCALL KEY_READ ;讀鍵盤 JBC 00H,N LJMP N0 ;無鍵,則跳到N0 N: LCALL CHAUNG ;有鍵則去刷新顯示狀態 LJMP LOOP N0: ;輸出當前時分秒 MOV R0,#60H MOV R1,#07H MOV R5,#08H LCALL COUNT_OUTPUT ;刷新輸出 LCALL SHOW ;輸出 LCALL CHANG_TIME ;按秒改變輸出時間 LJMP LOOP FRIST: MOV SP,#30H ;設置堆棧 MOV 45H,#01H ;設置初始狀態為00H MOV P1,#0FFH ;初始化P1口 MOV TMOD,#21H ;設置定時器工作模式,T0為工作模式2,T1為工作模式1 MOV 50H,#06H ;初始化年月日 數碼管顯示 MOV 51H,#00H MOV 52H,#09H MOV 53H,#00H MOV 54H,#00H MOV 55H,#01H MOV 56H,#00H MOV 57H,#02H MOV 46H,#14H ;初始化年月日 MOV 47H,#0AH MOV 48H,#09H MOV 49H,#06H MOV 60H,#00H ;初始化時 分 秒 數碼管顯示 MOV 61H,#00H MOV 62H,#08H MOV 63H,#05H MOV 64H,#02H MOV 65H,#02H MOV 66H,#00H MOV 67H,#00H MOV 58H,#16H ;初始化時分秒 MOV 59H,#3AH MOV 68H,#00H MOV R6,#19H ;定時T1計數 MOV R7,#28H MOV TH0,#15H ;賦T0定時初值 MOV TL0,#0A0H MOV TH1,#06H ;賦T1定時初值 MOV TL1,#06H SETB TR1 CLR 00H ;初始化按鍵標志為“0” , 即 無 鍵 CLR 01H ;初始化鍵值為“0”,即A CLR 02H ;初始化按鍵長短為“0”,即短按鍵 CLR 03H ;初始化定時T1標志 CLR 04H ;初始時間更改標志位(秒,分,時,日,月,年) CLR 05H CLR 06H CLR 07H CLR 08H CLR 09H CLR 0AH CLR 0BH ;01狀態標志位,表示為01狀態 MOV IE,#88H ;開定時中斷 RET /*輸出計算子程序*/ COUNT_OUTPUT: JBC 04H,COUNT_S ;秒改變,則計算出顯示值送相應內存 LJMP COUNT_M COUNT_S: ;否則去計算分 MOV B,#0AH ;秒/10。商送61H,余數送60H MOV A,68H DIV AB MOV 61H,A MOV 60H,B COUNT_M: JBC 05H,COUNT_M0 ;分改變,則計算出顯示值送相應內存 LJMP COUNT_H ;否則去計算時 COUNT_M0: MOV B,#0AH ;分/10,商送63H,余數送62H MOV A,59H DIV AB MOV 63H,A MOV 62H,B COUNT_H: JBC 06H,COUNT_H0 ;時改變,則計算出顯示值送相應內存 LJMP COUNT_D ;否則去計算日 COUNT_H0: MOV B,#0AH ;時/10,商送65H,余數送64H MOV A,58H DIV AB MOV 65H,A MOV 64H,B COUNT_D: ;日改變,則計算出顯示值送相應內存 JBC 07H,COUNT_D0 ;否則去計算月 LJMP COUNT_MON COUNT_D0: ;日/10,商送51H,余數送50H MOV B,#0AH MOV A,49H DIV AB MOV 51H,A MOV 50H,B COUNT_MON: JBC 08H,COUNT_MON0 ;月改變,則計算出顯示值送相應內存 LJMP COUNT_YL ;否則去計算年(L) COUNT_MON0: MOV B,#0AH ;月/10,商送53H,余數送52H MOV A,48H DIV AB MOV 53H,A MOV 52H,B COUNT_YL: JBC 09H,COUNT_YL0 ;年低位改變,則計算出顯示值送相應內存 LJMP COUNT_YH ;否則去計算年(H) COUNT_YL0: MOV B,#0AH ;年(L)/10,商送55H,余數送54H MOV A,47H DIV AB MOV 55H,A MOV 54H,B COUNT_YH: ;年高改變,則計算出顯示值送相應內存 JBC 0AH,COUNT_YH0 ;否則子程序返回 LJMP COUNT_RETURN COUNT_YH0: MOV B,#0AH ;年(H)/10,商送57H,余數送56H MOV A,46H DIV AB MOV 57H,A MOV 56H,B COUNT_RETURN: RET /*時間修改子程序*/ CHAUNG: STAR: MOV A,45H ;讀狀態值 CJNE A,#01H,CHAUNG0 ;狀態值=01H,則轉H_M_S0,否則進行下一個判斷 LCALL H_M_S0 LJMP CHAUNG10 CHAUNG0: CJNE A,#02H,CHAUNG1 ;狀態值=02H,則轉H_M_S1,否則進行下一個判斷 LCALL H_M_S1 LJMP CHAUNG10 CHAUNG1: CJNE A,#04H,CHAUNG3 ;狀態值=04H,則轉H_M_S2,否則進行下一個判斷 LCALL H_M_S2 LJMP CHAUNG10 CHAUNG3: CJNE A,#03H,CHAUNG4 ;狀態值=03H,則轉Y_M_D0,否則進行下一個判斷 LCALL Y_M_D0 LJMP CHAUNG10 CHAUNG4: CJNE A,#06H,CHAUNG5 ;狀態值=06H,則轉Y_M_D1,否則進行下一個判斷 LCALL Y_M_D1 LJMP CHAUNG10 CHAUNG5: CJNE A,#0CH,CHAUNG6 ;狀態值=0cH,則轉Y_M_D2,否則進行下一個判斷 LCALL Y_M_D2 CHAUNG6: CJNE A,#18H,CHAUNG7 ;狀態值=18H,則轉Y_M_D3,否則進行下一個判斷 LCALL Y_M_D3 LJMP CHAUNG10 CHAUNG7: CJNE A,#07H,CHAUNG8 ;狀態值=07H,則轉S_CLOCK0,否則進行下一個判斷 LCALL S_CLOCK0 LJMP CHAUNG10 CHAUNG8: CJNE A,#0EH,CHAUNG9 ;狀態值=0eH,則轉S_CLOCK1,否則進行下一個判斷 LCALL S_CLOCK1 LJMP CHAUNG10 CHAUNG9: CJNE A,#1CH,CHAUNG10 ;狀態值=07H,則轉S_CLOCK2,否則進行下一個判斷 LCALL S_CLOCK2 LJMP CHAUNG10 CHAUNG10: ;子程序返回 JBC 0BH,STAR RET /*狀態01修理子程序*/ H_M_S0: JB 01H,S_01 ;判斷A鍵,B鍵 MOV 45H,#02H ;A鍵,狀態轉為02H LJMP S_01_RETURN S_01: ;B鍵,狀態轉為03H MOV 45H,#03H S_01_RETURN: SETB 0BH RET /*狀態02修理子程序*/ H_M_S1: MOV 69H,#00H ;定時標志,定時到,回到A狀態 LOOP_02: MOV R0,#64H ;設置顯示內容 MOV R1,#03H MOV R5,#02H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_02 ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_02 ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_02_RETURN S_02: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_02_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_02_1 ;短按,去判斷A鍵B鍵 INC 58H ;A鍵,時+1 SETB 06H ;置位,時改變標志 LJMP LOOP_02 S_02_0: JBC 01H,S_02_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#04H ;A鍵,狀態轉為04H SETB 0BH LJMP S_02_RETURN S_02_1: ;短按B鍵,時-1,并置位時改變標志 DEC 58H SETB 06H LJMP LOOP_02 S_02_2: MOV 45H,#01H S_02_RETURN: MOV 68H,#00H RET /*狀態04處理子程序*/ H_M_S2: MOV 69H,#00H ;定時標志,定時到,回到A狀態 LOOP_04: MOV R0,#62H ;設置顯示內容 MOV R1,#05H MOV R5,#02H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_04 ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_04 ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_02_RETURN S_04: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_04_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_04_1 ;短按,去判斷A鍵B鍵 INC 59H ;A鍵,分+1 SETB 05H ;置位,分改變標志 LJMP LOOP_04 S_04_0: JBC 01H,S_04_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#01H ;A鍵,狀態轉為08H LJMP S_04_RETURN S_04_1: ;短按B鍵,分-1,并置位分改變標志 DEC 59H SETB 05H LJMP LOOP_04 S_04_2: MOV 45H,#01H S_04_RETURN: MOV 68H,#00H RET /*狀態03修理子程序*/ Y_M_D0: MOV R0,#50H MOV R1,#07H MOV R5,#08H LCALL COUNT_OUTPUT LCALL SHOW LCALL KEY_READ JB 01H,S_03 ;判斷A鍵,B鍵 MOV 45H,#06H ;A鍵,狀態轉為02H LJMP S_03_RETURN S_03: ;B鍵,狀態轉為03H MOV 45H,#07H S_03_RETURN: SETB 0BH RET /*狀態06修理子程序*/ Y_M_D1: MOV 69H,#00H ;定時標志,定時到,回到A狀態 LOOP_06: MOV R0,#54H ;設置顯示內容 MOV R1,#03H MOV R5,#04H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_06 ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_06 ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_06_RETURN S_06: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_06_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_06_1 ;短按,去判斷A鍵B鍵 INC 47H ;A鍵,年+1 MOV A,47H CJNE A,#64H,S_066 MOV 47H,#00H INC 46H SETB 0AH S_066: SETB 09H ;置位,年改變標志 LJMP LOOP_06 S_06_0: JBC 01H,S_06_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#01H ;A鍵,狀態轉為08H LJMP S_06_RETURN S_06_1: ;短按B鍵,年-1,并置位年改變標志 DEC 47H MOV A,47H CJNE A,#-1,S_0666 MOV 47H,#00H DEC 46H SETB 0AH S_0666: SETB 09H LJMP LOOP_06 S_06_2: MOV 45H,#01H S_06_RETURN: RET /*狀態0C修理子程序*/ Y_M_D2: MOV 69H,#00H ;定時標志,定時到,回到A狀態 LOOP_0C: MOV R0,#52H ;設置顯示內容 MOV R1,#05H MOV R5,#02H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_0C ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_0C ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_0C_RETURN S_0C: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_0C_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_0C_1 ;短按,去判斷A鍵B鍵 INC 48H ;A鍵,月+1 SETB 08H ;置位,月改變標志 LJMP LOOP_0C S_0C_0: JBC 01H,S_0C_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#01H ;A鍵,狀態轉為08H LJMP S_0C_RETURN S_0C_1: ;短按B鍵,月-1,并置位月改變標志 DEC 48H SETB 08H LJMP LOOP_0C S_0C_2: MOV 45H,#01H S_0C_RETURN: RET /*狀態18修理子程序*/ Y_M_D3: MOV 69H,#00H ;定時標志,定時到,回到A狀態 LOOP_18: MOV R0,#50H ;設置顯示內容 MOV R1,#07H MOV R5,#02H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_18 ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_18 ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_18_RETURN S_18: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_18_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_18_1 ;短按,去判斷A鍵B鍵 INC 49H ;A鍵,日+1 SETB 07H ;置位,日改變標志 LJMP LOOP_18 S_18_0: JBC 01H,S_18_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#01H ;A鍵,狀態轉為08H LJMP S_18_RETURN S_18_1: ;短按B鍵,日-1,并置位日改變標志 DEC 49H SETB 07H LJMP LOOP_18 S_18_2: MOV 45H,#01H S_18_RETURN: MOV 68H,#00H RET /*狀態07修理子程序*/ S_CLOCK0: JB 01H,S_07 ;判斷A鍵,B鍵 MOV 45H,#01H ;A鍵,狀態轉為02H LJMP S_07_RETURN S_07: ;B鍵,狀態轉為03H MOV 45H,#07H S_07_RETURN: SETB 0BH RET /*狀態0E修理子程序*/ S_CLOCK1: LOOP_0E: MOV R0,#62H ;設置顯示內容 MOV R1,#05H MOV R5,#02H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_0E ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_0E ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_18_RETURN S_0E: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_0E_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_0E_1 ;短按,去判斷A鍵B鍵 INC 59H ;A鍵,分+1 SETB 05H ;置位,時改變標志 LJMP LOOP_0E S_0E_0: JBC 01H,S_0E_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#01H ;A鍵,狀態轉為08H LJMP S_0E_RETURN S_0E_1: ;短按B鍵,分-1,并置位時改變標志 DEC 59H SETB 05H LJMP LOOP_0E S_0E_2: MOV 45H,#01H S_0E_RETURN: MOV 68H,#00H RET /*狀態1C修理子程序*/ S_CLOCK2: LOOP_1C: MOV R0,#62H ;設置顯示內容 MOV R1,#05H MOV R5,#02H LCALL COUNT_OUTPUT ;計算顯示數據 LCALL SHOW ;顯示 LCALL KEY_READ ;讀鍵盤 JBC 00H,S_1C ;有鍵,則去判斷長按短按 INC 69H ;無鍵,定時標志+1 MOV A,69H CJNE A,#0FFH,LOOP_1C ;定時到,狀態轉為01H,子程序返回 MOV 45H,#01H LJMP S_1C_RETURN S_1C: MOV 69H,#00H ;有按鍵,清零定時標志 JBC 02H,S_1C_0 ;長按,去判斷A鍵B鍵 JBC 01H,S_1C_1 ;短按,去判斷A鍵B鍵 INC 59H ;A鍵,分+1 SETB 05H ;置位,時改變標志 LJMP LOOP_1C S_1C_0: JBC 01H,S_1C_2 ;長按,B鍵,狀態變為了01H,并子程序返回 MOV 45H,#01H ;A鍵,狀態轉為08H LJMP S_1C_RETURN S_1C_1: ;短按B鍵,分-1,并置位時改變標志 DEC 59H SETB 05H LJMP LOOP_1C S_1C_2: MOV 45H,#01H S_1C_RETURN: MOV 68H,#00H RET /*時間按秒增長子程序*/ CHANG_TIME: JBC 03H,C_TIME ;秒定時標志是否為1,為1則去改變時間,否則子程序返回 LJMP C_RETURN C_TIME: MOV A,68H ;讀出秒,加1,判斷是否大于等于60,是則送#00H到68H,否則將秒寫回68H INC A SETB 04H CJNE A,#3CH,S ;僅當秒大于等于60時,才去改變分 MOV 68H,#00H LJMP M0 S: MOV 68H,A LJMP C_RETURN M0: MOV A,59H ;讀出分,加1,判斷是否大于等于60,是則送#00H到59H,否則將秒寫回59H INC A SETB 05H CJNE A,#3CH,M1 ;僅當分大于等于60時,才去改變時 MOV 59H,#00H LJMP H0 M1: MOV 59H,A LJMP C_RETURN H0: MOV A,58H ;讀出時,加1,判斷是否大于等于24,是則送#00H到58H,否則將秒寫回58H INC A SETB 06H CJNE A,#18H,H1 ;僅當時大于等于24時,才去改變日 MOV 58H,#00H LJMP DAY0 H1: MOV 58H,A LJMP C_RETURN DAY0: MOV A,49H ;讀出日,加1,判斷是否大于等于31,是則送#01H到49H,否則將秒寫回49H INC A SETB 07H CJNE A,#1EH,DAY1 ;僅當日大于等于30時,才去改變月 MOV 49H,#01H LJMP MON0 DAY1: MOV 49H,A LJMP C_RETURN MON0: MOV A,48H ;讀出月,加1,判斷是否大于等于13,是則送#01H到48H,否則將秒寫回48H INC A SETB 08H CJNE A,#0CH,MON1 ;僅當月大于等于13時,才去改變年 MOV 48H,#01H LJMP YEARL0 MON1: MOV 48H,A LJMP C_RETURN YEARL0: MOV A,47H ;讀出年(L),加1,判斷是否大于等于100,是則送#00H到48H,否則將秒寫回47H INC A SETB 09H CJNE A,#64H,YEARL1 ;僅當年(L)大于等于100時,才去改變年(H) MOV 47H,#00H LJMP YAERH0 YEARL1: MOV 47H,A LJMP C_RETURN YAERH0: MOV A,46H ;讀出年(H),加1,判斷是否大于等于100,是則送#00H到48H,否則將秒寫回46H INC A SETB 0AH CJNE A,#64H,YEARH1 MOV 46H,#00H LJMP C_RETURN YEARH1: MOV 46H,A C_RETURN: RET /*數碼管顯示子程序,R0存顯示內容首址,R1存位選首址 ,*/ SHOW: MOV DPTR,#LED_DATA S2: MOV A,R1 RL A RL A MOV P2,A MOV A,@R0 MOVC A,@A+DPTR CPL A MOV P0,A INC R0 DEC R1 MOV R4,#01H LCALL DELAY DJNZ R5,S2 MOV R4,#01H LCALL DELAY RET /*鍵盤掃描子程序*/ KEY_READ: JB P1.0,NEXT MOV R4,#64H LCALL DELAY JB P1.0,NEXT SETB TR0 SETB 00H CLR 01H JNB P1.0,$ CLR TR0 JNB TF0,KEY_RETUN SETB 02H LJMP KEY_RETUN NEXT: JB P1.2,KEY_RETUN MOV R4,#64H LCALL DELAY JB P1.2,KEY_RETUN SETB TR0 SETB 00H SETB 01H JNB P1.2,$ CLR TR0 JNB TF0,KEY_RETUN SETB 02H LJMP KEY_RETUN KEY_RETUN: MOV TH0,#15H ;重賦T0定時初值 MOV TL0,#0A0H CLR TF0 RET /*定時器T1中斷服務子程序*/ INT_T1: PUSH ACC DJNZ R6,INT_1 MOV R6,#50H DJNZ R7,INT_1 MOV R7,#32H SETB 03H INT_1: POP ACC RETI /*延時子程序,R2,R3為定時常數,R4為定時變量*/ DELAY: D: MOV R2,#0AH D0: MOV R3,#0AH D1: DJNZ R3,D1 DJNZ R2,D0 DJNZ R4,D RET /*數碼管顯示代碼,0~F*/ LED_DATA: DB 03H,9FH,25H,0DH,99H,49H,41H,1FH DB 01H,09H,11H,0C1H,63H,85H,61H,71H END