- ;**************************************************
- ;平凡单片机工作室 作者:周坚
- ;(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
复制代码
|