⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cntrl.asm

📁 Small RTOS51是为51系列单片机而编写的。它是完全免费的、源代码公开的多任务实时操作系统。它可在无任何外部数据存储器的单片80C51系统上运行
💻 ASM
字号:
;**************************************************
;    平凡单片机工作室
;  http://www.mcustudio.com
;   (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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -