基于Proteus+8051汇编应用实例系列之四--4×4键盘矩阵控制条形LED显示

题目描述:
4X4键盘分别连到P1口的8个引脚,其中低四位控制行,高四位控制列,有一排条形LED灯分别连至P2和P3口,要通过汇编代码实现按下一个按钮,则对应个数的LED灯亮起,例如按下第8个按钮,则上面8个灯亮,按下第13个按钮,则亮13个灯,对应的Proteus仿真图如下所示:


训练目的:
1)矩形键盘的扫描方法
2)模块化编写代码
3)基本运算,如减法,移位等
直奔代码吧……
代码文件main.asm

// 矩阵键盘控制LED灯
// 4X4矩阵键盘连到P1口上
// 16个LED灯依次连到P2和P3口上
// IO口作为输入口时,要先给他置1才能接受外接的信号,遇1则1,遇0则0
		ORG	00H
// *************************************
// 初始化工作
// *************************************		
START:
		//// 使LED全灭状态
		MOV R1,#0FFH
		MOV R2,#0FFH
		MOV P2,R1
		MOV P3,R2
// *************************************
// 主循环
// *************************************		
MAIN_LOOP:
		MOV A,#0F0H				//使低四位(行)为0,高四位(列)为1,同时让列脚处于输入状态
		MOV P1,A
		CALL SCAN_KEYS
		JMP	MAIN_LOOP

// *************************************
// 检测键盘
// *************************************		
SCAN_KEYS:
		MOV 	A,P1
		CJNE	A,#0F0H,CHECK_KEY	//无键被按下时返回,结束此次检测
		RET
// *************************************
// 按键处理过程
// *************************************		
CHECK_KEY:
		CALL LOCATE_COL
		CALL DELAY
FRESH_STATE:
		MOV A,P1
		//// 由于在检测行时,更换了P1的初始值为0FH,所以这里与0FH比较,而不是#0F0H
		CJNE	A,#0FH,FRESH_STATE		//去抖,直到键被松开时(相等)执行下面的语句
		////列序号存在R1中,行序号在R2中
		CALL SHOW_LED
		RET
// *************************************
// 定位按钮所在列
// *************************************		
LOCATE_COL:
		//// 先定位列,根据低四位为零时,找哪一列对应的脚本是零即可
		CJNE	A,#0E0H,COL_2		//检测是否为第一列
		MOV R1,#1
		JMP	LOCATE_ROW
COL_2:
		CJNE	A,#0D0H,COL_3	//检测是否为第二列,若不是跳至检测下一列
		MOV R1,#2
		JMP	LOCATE_ROW
COL_3:
		CJNE	A,#0B0H,COL_4	//检测是否为第三列
		MOV R1,#3
		JMP LOCATE_ROW
COL_4:							//检测是否为第四列
		CJNE	A,#70H,RETURN
		MOV R1,#4
		JMP LOCATE_ROW

// *************************************
// 定位按钮所在行
// 使高四位(列)为零,低四位(行)为1,检测低四位中哪个变为了零,即可定位行数
// *************************************		
LOCATE_ROW:
		MOV A,#0FH
		MOV P1,A
		MOV A,P1
		CJNE	A,#0EH,ROW_2
		MOV R2,#1
		RET
ROW_2:
		CJNE	A,#0DH,ROW_3
		MOV R2,#2
		RET
ROW_3:
		CJNE	A,#0BH,ROW_4
		MOV R2,#3
		RET
ROW_4:
		CJNE	A,#07H,RETURN
		MOV R2,#4
		RET
// *********************************************************
//显示相应的LED状态
// *********************************************************
SHOW_LED:
		//// 列序号减1然后乘以4加行序号等于键的序号
		
		MOV A,R1						//刷新灯的状态
		SUBB	A,#1
		MOV B,#4
		MUL AB					//结果低8位在A里
		ADD	A,R2				//得到键序号
		MOV R3,A
		//// 当键序号为8时,则直接让上面(P2口)8个全亮, 下面8个(P3口)全灭
		CJNE	A,#8,CAL_LED
		MOV R1,#00H
		MOV R2,#0FFH
		MOV P2,R1
		MOV P3,R2
		RET
CAL_LED:
		SUBB	A,#8			//带借位减法,若有借位则进(借)位标识Cy为1
		JNC	SET_LED
		//// 分支1:A小于8,减的结果小于0时,则只让P2口亮相应数目的灯,下面P3口全灭
		MOV A,R3
		MOV R1,A
		MOV R2,#0FFH
		MOV P3,R2
		MOV A,#0FFH
P2_WEI_LED:
		CLR C
		RLC	A
		DJNZ	R1,P2_WEI_LED
		MOV P2,A
		RET
		
SET_LED:
		//// 分支2:键序号大于8时,让P2口的灯全亮,下面P3口亮相应数目(减的结果)的灯
		
		MOV R1,#00H
		MOV R2,A
		MOV P2,R1
		MOV A,#0FFH
P3_WEI_LED:
		CLR C
		RLC	A
		DJNZ	R2,P3_WEI_LED
		MOV P3,A
		RET
		
// *************************************
RETURN:
		RET
// *************************************
// 延时30ms
// *************************************
DELAY:
		MOV R5,#30
D1:		MOV R6,#20
D2:		MOV R7,#248
		DJNZ	R7,$
		DJNZ	R6,D2
		DJNZ	R5,D1
		RET

		END

注:1)模块化编程,Call和RET的配对使用,完成一个子过程,并相互嵌套,完成复杂的任务过程,编写过程也是一步步实现,每实现一步通过仿真测试成功,再做下一步,确保了程序质量。2)深入理解单片机I/O口的输入输出,先置高电位,使该引脚处理接受输入状态,(原理根据期电路结构, 为0时并不能接收到外接电平的)3)代码段SCAN_KEYS:理解矩形键盘的扫描过程,先给P1口赋值为# 0F0H,即低四位(行)为0,高四位为1,然后不断地读取P1口的值,若值仍保持原值#0F0H,则说明没有键被按下,若值发生变化,则进一步判断高四位中哪个变为低电平,则对应的列中的键被按下,即找到列序号,依据同样的道理,此时让低四位为1,高四位为0,然后看低四位中哪一个变为0,即确定行数,有了行序号和列序号即可确定键的序号,进而通过LED灯的状态来点亮相应数目的灯(此过程中又涉及减法及移位实现对应数目的灯变亮)4)代码段SHOW_LED:实现了键序号到灯个数的转换,涉及了SUBB,RLC等操作。5)代码段CHECK_KEY:检测键和去抖过程的结合,先执行定位键,然后再延时,直到键被松开。

你可能感兴趣的:(单片机,Proteus,51汇编)