- ;**************************************************
- ;平凡單片機工作室 作者:周堅
- ;(c) Copyright 2003 Pingfan's McuStudio
- ;All rights Reserved
- ;cntrl.asm
- ;實驗:姬家寨電子科技實驗室:姬學瑞
- ;功能描述:汽車傳感器控制儀程序,具體內容請參考書
- ;**************************************************
- ;鍵盤緩沖區
- FIFO1 DATA 30H
- FIFO2 DATA 31H
- FIFO3 DATA 32H
- ;以下顯示緩沖區
- DISP1 DATA 40H
- DISP2 DATA 41H
- DISP3 DATA 42H
- DISPCTRL DATA 43H
- ;顯示控制字
- DISP_CTRL BIT 42H ;顯示控制字,如果為1顯示,為0不顯示
- ;鍵盤有鍵按下標志
- K_MARK BIT 41H
- ;控制字堆棧
- STAC DATA 50H
- ;由FIFO得到的控制字
- CTRL DATA 33H
- ORG 0000H
- AJMP START
- ORG 40H
- START:
- MOV SP,#5FH ; 設置堆棧
- MOV P1,#0FFH
- MOV P2,#00H
- MOV P0,#0FFH
- SETB DISP_CTRL ;調用顯示程序前設置該位,要求顯示出來
- MOV DISP3,#8
- MOV DISP2,#8
- MOV DISP1,#8
- ACALL DISP ;顯示888
- ACALL D1S ;延時1S
- MOV DISP3,#16 ;H字符的代碼
- MOV DISP2,#17 ;消隱代碼
- MOV DISP1,#17
- ACALL DISP
- CLR A
- MOV DISPCTRL,A ;
- MOV R0,#20H
- MOV R7,#10H
- INIT:
- MOV @R0,A
- INC R0
- DJNZ R7,INIT ;清除20H到2FH單元的內容
- SETB DISP_CTRL
- MOV DISPCTRL,#10
- MOV FIFO1,#0
- MOV FIFO2,#0
- MOV FIFO3,#0
- MAIN:
- INC DISPCTRL
- MOV A,DISPCTRL
- JZ RDISP
- AJMP MKEY
- RDISP:
- MOV DISPCTRL,#10
- ACALL DISP ;如果計數到255次,則刷新一次顯示
- MKEY:
- ACALL KEY ;調用鍵盤處理程序
- JB K_MARK,KEY_PROC ;如果有鍵被按下,則轉去鍵盤處理
- ;***************************以下將內存對應內容輸出
- MOV A,20H
- NOP
- MOV 20H,A ;取出20H內容,再轉入20H
- MOV P0,A
- SETB P2.3
- ACALL DOUT
- CLR P2.3 ;延時形成下降沿脈沖
- ;*******************************
- MOV A,21H
- NOP
- MOV 21H,A
- MOV P0,A
- SETB P2.4
- ACALL DOUT
- CLR P2.4
- ;*******************************
- MOV A,22H
- NOP
- MOV 22H,A
- MOV P0,A
- SETB P2.5
- ACALL DOUT
- CLR P2.5
- ;*********************************
- MOV A,23H
- NOP
- MOV 23H,A
- MOV P0,A
- SETB P2.6
- ACALL DOUT
- CLR P2.6
- MOV A,24H
- ;********************************
- MOV A,24H
- NOP
- MOV 24H,A
- MOV P0,A
- SETB P2.7
- ACALL DOUT
- CLR P2.7
- AJMP MAIN
- ;用于輸出的延時程序
- DOUT:
- PUSH PSW
- SETB RS1
- MOV R6,#3
- DJNZ R6,$
- POP PSW
- RET
- ;*****************************鍵盤處理
- ;數字鍵直接進入鍵值FIFO
- ;功能鍵分別處理
- ;A:判斷待顯示的是否是合法的代碼,是則接受,并根據代碼作相應動作,顯示閃爍
- ;一次,如果不是合法的代碼,則不接受,并不閃爍
- ;合法的代碼為: 001-032,使各相位置1,使各繼電器吸合,斷路
- ; 033-040,使相應位置1,串入電阻
- ; 101-132,使相應位清0,各繼電器觸點吸合
- ;注意:
- ; 033-040代碼將相應的0-7位清0,以防止繼電器觸點斷路.
- ; 101-108代碼在除將相應的0-7位清0外,還要將32-39相應位清0,防止串入電阻
- ;B鍵:顯示和消隱的切換開關
- ;C鍵:復位開關,按下此鍵,將所有位(00-40)全部清0,使所有繼電器斷電(即全部觸點處
- ;于吸合狀態).
- KEY_PROC:
- CLR K_MARK ;清除有鍵按下標志
- CLR C ;清進位位
- MOV A,B ;取鍵值
- CJNE A,#10,KEY_NEXT1
- AJMP FUN_PROC ;如果鍵值等于10轉功能鍵處理
- KEY_NEXT1:
- JC DATA_PROC ;如果小于10,則到數字鍵處理
- AJMP FUN_PROC ;如果鍵值大于10則轉功能鍵處理
- DATA_PROC: ;數字鍵處理
- MOV FIFO3,FIFO2
- MOV FIFO2,FIFO1
- MOV FIFO1,B ;如果是數字鍵,則將數字進入FIFO
- MOV DISP3,FIFO3
- MOV DISP2,FIFO2
- MOV DISP1,FIFO1
- ACALL DISP ;調用顯示程序
- AJMP MAIN ;數字程序處理完畢,重新開始循環
- ;***************************以下各功能鍵處理部份
- A_PROC: ;A鍵處理
- MOV A,FIFO3 ;取FIFO的首字節
- CLR C
- CJNE A,#2,A_1
- A_ERR:
- AJMP MAIN
- A_1:
- JC A_2
- AJMP MAIN
- A_2:
- MOV A,FIFO3 ;取首字節
- MOV B,#100
- MUL AB
- MOV R0,A
- MOV A,FIFO2
- MOV B,#10
- MUL AB
- ADD A,R0
- ADD A,FIFO1
- MOV R0,A
- CJNE A,#141,A_3
- AJMP MAIN
- A_3:
- JC A_4
- AJMP MAIN
- A_4:
- MOV A,R0
- CJNE A,#100,A_5
- AJMP MAIN
- A_5:
- JC A_6
- AJMP A_ACTION1
- A_6:
- MOV A,R0
- CJNE A,#41,A_7
- AJMP MAIN
- A_7:
- JC A_8
- AJMP MAIN
- A_ACTION1:
- DEC R0
- MOV CTRL,R0
- ACALL CLR_OUT
- CLR DISP_CTRL
- ACALL DISP
- ACALL D1S
- SETB DISP_CTRL
- ACALL DISP ;開顯示并閃爍一次
- AJMP MAIN
- A_8:
- MOV A,R0
- JNZ A_ACTION2
- AJMP MAIN
- A_ACTION2:
- DEC R0
- MOV CTRL,R0
- ACALL SET_OUT
- CLR DISP_CTRL
- ACALL DISP ;關顯示
- ACALL D1S
- SETB DISP_CTRL
- ACALL DISP ;閃爍一次
- AJMP MAIN
- FUN_PROC:
- MOV A,B
- SUBB A,#10
- JZ A_PROC
- DEC A
- JZ B_PROC ;B鍵處理
- DEC A
- JZ C_PROC ;C 鍵處理
- DEC A
- JZ D_PROC ;D鍵處理
- DEC A
- JZ E_PROC ;E 鍵處理
- DEC A
- JZ F_PROC ;F鍵處理
- KEY_ERR: ;如果不是以上鍵(可能雙鍵同時按下之類)
- NOP ;錯誤處理,在此直接返回即可。
- AJMP MAIN
- B_PROC:
- CPL DISP_CTRL ;取反顯示控制
- ACALL DISP
- LJMP MAIN
- C_PROC:
- MOV 20H,#00H
- MOV 21H,#00H
- MOV 22H,#00H
- MOV 23H,#00H
- MOV 24H,#00H ;C鍵是開關重置鍵,將所有位清零
- MOV DISP3,#16 ;'H'
- MOV DISP2,#17 ;消隱
- MOV DISP1,#17 ;消隱
- ACALL DISP
- LJMP MAIN
- D_PROC:
- LJMP MAIN
- E_PROC:
- LJMP MAIN
- F_PROC:
- LJMP MAIN ;這四個鍵暫不使用
- ;**************************************置位
- SET_OUT:
- CLR C
- MOV A,CTRL ;CTRL是要設置的位
- CJNE A,#32,SET1
- AJMP SETPROC ;等于32要特殊處理
- SET1:
- JNC SETPROC ;大于32要特殊處理
- SET2: ;是1-32中的一個值
- MOV A,CTRL
- ACALL SETOUT1
- SETPROC: ;如果大于等于32,則作兩個動作:
- MOV A,CTRL ;1.將相應位置1,以串入電位器
- ACALL SETOUT1 ;將相應的1-8位清0,以接通電路
- MOV A,CTRL
- SUBB A,#31
- ADD A,#100
- ACALL CLROUT1
- RET
- SETOUT1:
- MOV B,#8 ;先將哪個字節要設置求出
- DIV AB
- PUSH PSW
- SETB RS0 ;選第二工作區
- MOV R0,#1FH ;用R0作間址尋址
- INC A
- MOV R7,A
- LP:
- INC R0
- DJNZ R7,LP ;確定是哪個字節
- ;**************************************
- MOV A,B ;將除得的結果送A(哪一位)
- JZ LP3 ;如果是0,直接轉,否則會有錯
- MOV A,@R0 ;取這個字節
- MOV R7,#8 ;將這個字節循環右移8次
- MOV R6,B ;分兩段,一段由R6控制,正好將該位移到ACC.0的位置
- LP1:
- DEC R7 ;R7中減去R6已移的次數
- RR A
- DJNZ R6,LP1
- SETB ACC.0 ;由R6控制的移動結束,該位處于ACC.0位置,置該位
- LP2:
- RR A
- DJNZ R7,LP2 ;剩下來該移動的次數由R7中的值決定
- AJMP LP4
- LP3: ;這個是用來處理一種特殊情況,即某一字節的最低位
- MOV A,@R0 ;此時B中是0,如果仍用上法處理,會出錯,只要直接將
- SETB ACC.0 ;該位置1即可
- LP4:
- MOV @R0,A
- POP PSW
- RET
- CLR_OUT:
- CLR C
- MOV A,CTRL ;CTRL是要清的位
- CJNE A,#107,CLR1
- AJMP CLRPROC ;等于107,轉
- CLR1:
- JC CLRPROC ;小于107,轉
- MOV A,CTRL
- ACALL CLROUT1
- CLRPROC: ;如果輸入的代碼是101-108,則作如下2個動作:
- MOV A,CTRL ;1.將相應位清0,使繼電器觸點吸合
- ACALL CLROUT1 ;2.將133-140相應位清0,使繼電器觸點吸合
- MOV A,CTRL ;防止串入電阻
- ADD A,#32
- ACALL CLROUT1
- RET
- CLROUT1:
- CLR C
- SUBB A,#100 ;先減去100 (因為該位為位數加上100構成)
- MOV B,#8 ;先將要清零的字節求出
- DIV AB
- PUSH PSW
- SETB RS0 ;選第二工作區
- MOV R0,#1FH ;用R0作間址尋址
- INC A
- MOV R7,A
- CLP:
- INC R0
- DJNZ R7,CLP ;確定是哪個字節
- ;**************************************
- MOV A,B ;將除得的結果送A(哪一位)
- JZ CLP3 ;如果是0,直接轉,否則會有錯
- MOV A,@R0 ;取這個字節
- MOV R7,#8 ;將這個字節循環右移8次
- MOV R6,B ;分兩段,一段由R6控制,正好將該位移到ACC.0的位置
- CLP1:
- DEC R7 ;R7中減去R6已移的次數
- RR A
- DJNZ R6,CLP1
- CLR ACC.0 ;由R6控制的移動結束,該位處于ACC.0位置,清該位
- CLP2:
- RR A
- DJNZ R7,CLP2 ;剩下來該移動的次數由R7中的值決定
- AJMP CLP4
- CLP3: ;這個是用來處理一種特殊情況,即某一字節的最低位
- MOV A,@R0 ;此時B中是0,如果仍用上法處理,會出錯,只要直接將
- CLR ACC.0 ;該位清0即可
- CLP4:
- MOV @R0,A
- POP PSW
- RET
- ;顯示子程序
- DISP:
- PUSH DPH
- PUSH DPL
- MOV SCON,#00H ;置串行口工作方式0
- JNB DISP_CTRL,HIDDEN ;如果DISP_CTRL位為0,則消隱處理
- AJMP DISP_NEXT ;要求消隱,則消隱處理
- HIDDEN:
- MOV A,#0FFH ;消隱代碼
- ACALL DISP_LED
- ACALL DISP_LED
- ACALL DISP_LED ;三次調用顯示子程序,發出3位
- POP DPL
- POP DPH
- RET ;消隱處理完畢,直接返回
- DISP_NEXT:
- MOV DPTR,#DISP_TAB
- MOV A,DISP3 ;顯示緩沖區的最高位
- MOVC A,@A+DPTR
- LCALL DISP_LED ;顯示最高位
- MOV A,DISP2
- MOVC A,@A+DPTR
- LCALL DISP_LED ;顯示中間位
- MOV A,DISP1
- MOV DPTR,#DISP_TAB
- MOVC A,@A+DPTR
- LCALL DISP_LED ;顯示低位
- POP DPL
- POP DPH
- RET
- ;以下顯示子程序
- DISP_LED:
- MOV SBUF,A
- DISP_L1:
- JNB TI,DISP_L1 ;發送第一位
- CLR TI
- RET
- DISP_TAB:
- DB 88H, 0BEH, 0C4H, 94H, 0B2H, 91H
- ; 0 1 2 3 4 5
- DB 81H, 0BCH, 80H, 090H, 0A0H, 83H
- ; 6 7 8 9 A B
- DB 0C9H, 86H, 0C1H, 0E1H, 0A2H, 0FFH
- ; C D E F H 消隱
- ;鍵盤程序
- ;返回的鍵值在B中
- KEY:
- CLR K_MARK
- MOV B,#0
- MOV R0,#0
- MOV R1,#0F7H
- MOV R7,#4
- MOV A,R1
- K_LOOP:
- MOV P1,A ;輸出到P1口
- MOV A,P1
- ORL A,#0FH ;高4位為1
- CPL A ;如果低4位也為1,取反后為0,無鍵按下
- JZ K_NEXT
- AJMP K_NEXT1
- K_NEXT:
- INC R0
- MOV A,R1
- RR A
- MOV R1,A
- DJNZ R7,K_LOOP
- AJMP NO_KEY
- K_NEXT1:
- JB ACC.4,K_RET ;0鍵被按下
- INC B
- INC B
- INC B
- INC B
- JB ACC.5,K_RET ;4鍵被按下
- INC B
- INC B
- INC B
- INC B
- JB ACC.6,K_RET ;8
- INC B
- INC B
- INC B
- INC B
- JB ACC.7,K_RET
- K_ERR:
- AJMP NO_KEY
- MOV A,R1
- RR A ;右移(F7--FB)
- MOV R1,A ;回存
- INC R0
- DJNZ R7,K_LOOP
- K_RET:
- MOV P1,#0F0H
- NOP
- MOV A,P1
- ORL A,#0FH
- CPL A
- JNZ K_RET ;循環直到所有按鍵被釋放
- SETB K_MARK ;置有鍵按下標志
- MOV A,B
- ADD A,R0
- MOV B,A
- RET
- NO_KEY:
- RET
- ;1秒延時子程序
- D1S:
- PUSH PSW
- SETB RS1
- MOV R7,#7FH
- DLP1:
- MOV R6,#8FH
- DLP2:
- MOV R5,#3
- DJNZ R5,$
- DJNZ R6,DLP2
- DJNZ R7,DLP1
- POP PSW
- RET
- ;10毫秒延時子程序
- D10MS:
- PUSH PSW
- MOV R7,#20
- D1:
- MOV R6,#250
- DJNZ R6,$
- DJNZ R7,D1
- POP PSW
- RET
- END
復制代碼
|