标题:
汽车传感器控制仪程序代码
[打印本页]
作者:
das
时间:
2015-4-16 03:03
标题:
汽车传感器控制仪程序代码
;**************************************************
;平凡单片机工作室 作者:周坚
;(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
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1