51单片机按键计数显示程序(汇编)

345 阅读5分钟

题目
编写一个按键计数程序。如图所示,对“独立按键”的按键次数进行计数。8个独立按键的计数值采用16进制分别显示在“2*4位共阴数码管”中。每位计数溢出时,控制“蜂鸣器”报警。
在这里插入图片描述

接线:
8位独立按键接单片机P1
数码管8位段选接单片机P0
蜂鸣器接P2.7
数码管的位选由38译码器来控制,译码器的ABC分别接单片机的P2.0,P2.1,P2.2,

:这里的数码管位选(动态扫描)是由单片机的三个引脚按照38译码器的输出改变单片机引脚电平来实现的,反应到单片机的低三位来说就是循环输出0-7,这里不需要移位什么的,因为程序中直接使用的十进制数,单片机内部是按照二进制来处理,因此无需任何转换。

经过测试,完美运行,能够实现题目要求。
以下是运行图片:
在这里插入图片描述
在这里插入图片描述

以下为全部代码,若需完整工程文件请移步至这里进行下载工程代码
//宏定义KEYCOUNTER部分请自行加上,
//这部分是定义计数器这个变量代表的某个地址

		//伪指令			
		ORG 0000H
	   	AJMP START	   
		//按键程序
		ORG 0100H

START:	MOV SP, #60H			;堆栈指针
		MOV P1, #0FFH		;按键初始化
		MOV P0, #3FH			;段选初始化
		MOV R2, #0H			;位选初始化
		MOV R4, #08H	  		;8位数码管

		//8个计数器,分别存按键的次数
		MOV KEYCOUNTER1, #0H  ;计数器初始化为0
		MOV KEYCOUNTER2, #0H  
		MOV KEYCOUNTER3, #0H  
		MOV KEYCOUNTER4, #0H 
		MOV KEYCOUNTER5, #0H  
		MOV KEYCOUNTER6, #0H  
		MOV KEYCOUNTER7, #0H  
		MOV KEYCOUNTER8, #0H  


//************按键判别***************// 
KEY:  	MOV P1,#0FFH    	;P1口按键全写1(高电平)
	  	MOV A,P1			;将P1口状态读到A
	 	CPL A			    ;取反
	 	JZ DIS		   		;若A为0 ,无按键按下,跳转KEY重新扫描
	 	LCALL D10ms	   		;消抖
	 	MOV A,P1		    ;再次检测
	 	CPL A			    ;再取反
	 	JZ DIS		   		;若A为0 ,无按键按下,跳转KEY重新扫描
	  	JB ACC.0,PS0	    	;直接寻址位ACC.01则转移 PS0
		JB ACC.1,PS1	   		;以下同理
		JB ACC.2,PS2	    
		JB ACC.3,PS3	    
		JB ACC.4,PS4	   
		JB ACC.5,PS5	    
		JB ACC.6,PS61	    
		JB ACC.7,PS71
PS61:	LJMP PS6			;超出范围,因此用此方式进行跳转
PS71:	LJMP PS7	 
DIS:		LCALL DISP   		;跳转到数码管显示程序
		LJMP KEY

//***********按键处理函数****************//
PS0:  	JNB P1.0, PS0   	;判断P1.0的状态,为0则转移(说明按键未松开,原地等待)
		MOV R0, KEYCOUNTER1	;计数值存到寄存器
		INC R0				;计数器加1
		MOV KEYCOUNTER1, R0	;返回给计数器
		CJNE R0,#16,DIS		;R0不等于16则转移到显示程序		
		MOV KEYCOUNTER1, #0	;等于16就直接清零
		LCALL SOUND			;蜂鸣器报警
		LJMP DIS				;跳转到显示程序

PS1:  	JNB P1.1, PS1   		;和PS0按键处理函数一样			 
		MOV R0, KEYCOUNTER2	
		INC R0				
		MOV KEYCOUNTER2, R0	
		CJNE R0,#16,DIS
		MOV KEYCOUNTER2, #0			
		LCALL SOUND
		LJMP DIS

PS2:  	JNB P1.2, PS2   					 
		MOV R0, KEYCOUNTER3	
		INC R0				
		MOV KEYCOUNTER3, R0	
		CJNE R0,#16,RE	
		MOV KEYCOUNTER3, #0	
		LCALL SOUND
		LJMP DIS
						
PS3:  	JNB P1.3, PS3   					 
		MOV R0, KEYCOUNTER4	
		INC R0				
		MOV KEYCOUNTER4, R0	
		CJNE R0,#16,RE	
		MOV KEYCOUNTER4, #0
		LCALL SOUND	
		LJMP DIS

PS4:  	JNB P1.4, PS4   					 
		MOV R0, KEYCOUNTER5	
		INC R0				
		MOV KEYCOUNTER5, R0	
		CJNE R0,#16,RE	
		MOV KEYCOUNTER5, #0	
		LCALL SOUND
		LJMP DIS
				
PS5:  	JNB P1.5, PS5   					 
		MOV R0, KEYCOUNTER6	
		INC R0				
		MOV KEYCOUNTER6, R0	
		CJNE R0,#16,RE	
		MOV KEYCOUNTER6, #0	
		LCALL SOUND
		LJMP DIS

PS6:  	JNB P1.6, PS6   					 
		MOV R0, KEYCOUNTER7	
		INC R0				
		MOV KEYCOUNTER7, R0	
		CJNE R0,#16,RE	
		MOV KEYCOUNTER7, #0	
		LCALL SOUND
		LJMP DIS

PS7:  	JNB P1.7, PS7   					 
		MOV R0, KEYCOUNTER8	
		INC R0				
		MOV KEYCOUNTER8, R0	
		CJNE R0,#16,RE			
		MOV KEYCOUNTER8, #0	
		LCALL SOUND
RE:		LJMP DIS
								
D10ms: 	MOV R7,#25			;延时子程序,用于按键消抖
D1:   	MOV R6,#200
	   	DJNZ R6,$			;R6减10,原地跳转
	   	DJNZ R7,D1
	   	RET								 		 
		   
//*************显示子程序**************//
//P2口低3位为位选线 ----------R2
//P0口为段选线		 ----------R1
	   	ORG 0500H		   
DISP:    MOV A,R2		  	;读取位选
	   	MOV P2,A			;输出到端口
		
H1:		CJNE R2,#0,H2			;R2不等于0则转移
		MOV R1,KEYCOUNTER1	;将计数器的值传给R1寄存器(R1保存的段选数据)
		LJMP NEXT		;收到计数器的值以后直接跳转到下一步,不再执行中间程序

H2:		CJNE R2,#1,H3			;R2不等于1则转移
		MOV R1,KEYCOUNTER2
		LJMP NEXT

H3:		CJNE R2,#2,H4			;R2不等于2则转移
		MOV R1,KEYCOUNTER3
		LJMP NEXT
		
H4:		CJNE R2,#3,H5			;R2不等于3则转移
		MOV R1,KEYCOUNTER4
		LJMP NEXT

H5:		CJNE R2,#4,H6			;R2不等于4则转移
		MOV R1,KEYCOUNTER5
		LJMP NEXT

H6:		CJNE R2,#5,H7			;R2不等于5则转移
		MOV R1,KEYCOUNTER6
		LJMP NEXT

H7:		CJNE R2,#6,H8			;R2不等于6则转移
		MOV R1,KEYCOUNTER7
		LJMP NEXT

H8:		CJNE R2,#7,NEXT		;R2不等于7则转移
		MOV R1,KEYCOUNTER8
		LJMP NEXT
						
NEXT:	MOV A,R1			;将段选数据送到A
		MOV DPTR,#TAB		
		MOVC A,@A+DPTR		;查段码表
		MOV P0,A			;将段选数据送到端口
		INC R2		  		;循环显示位选	   	
		CJNE R2,#8,NEXT1		;R2最大为8,也就是只控制低3位(138译码器的输入端)
		MOV R2,#0	   		;清零				   	   	
NEXT1:	LCALL DELAY	  	
		DJNZ R4,DISP		;R4减1不为0则跳转到DISP,重新循环点亮其他几位数码管		RET
//********延时子程序********//
DELAY: 	MOV R5,#10
DEL0:  	MOV R6,#1
DEL1:  	MOV R7,#20
DEL2:  	DJNZ R7,DEL2
	   	DJNZ R6,DEL1
	   	DJNZ R5,DEL0	   	
		RET
//********共阴极数码管码表***********//
TAB:	DB  3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H

//*****蜂鸣器报警,IO口输出高电平*******//
	   	ORG 0800H
SOUND:  SETB P2.7
	    MOV R4,#64H	;延时100ms
LOOP:   MOV R3,#0F9H
LOOP1:  DJNZ R3,LOOP1
	    DJNZ R4,LOOP
	    CLR P2.7
	    RET
  
	    END