目录

一、 实验要求

二、 实验设计

1.整体思路

2.流程图

3.主要模块设计思路及分析

三、 实现效果

四、源代码

五、总结与思考


一、 实验要求

  1. 利用单片机开发板的矩阵键盘实现个人学号后8位的输入和显示。
  2. 利用矩阵键盘S1~S10输入数字1~0。(1~9+0)
  3. 利用数码管LED8~LED1从左到右显示8位学号

(矩阵按键的电路图如下)

        有上图可知:

        行:P1.7(第一行)~P1.4(第四行)

        列:P1.3(第一列)~P1.0(第四列)

二、 实验设计

1.整体思路

(1)START:初始化

(2)MAIN:如果有按键按下(R0值+1),则修改RAM中的值,RAM中的值存的是8个数码管段

        选应该有的值。

        调用数码管显示,数码管按照位选,分别点亮8个数码管。段选从RAM中取。

        查询是否有按键按下,没有的话就继续点亮数码管。有的话进行抖动消除。

(3)抖动消除:调用数码管显示来代替延时程序。再次查询是否有按键按下,没有回到MAIN中

        的数码管显示,有的话查询是哪一个按键按下。

(4)查询按键:查询按键的号码后,保存到A。回到MAIN中,修改RAM中的当前数码管所对应

        的段选值。然后继续数码管的显示。

2.流程图

        以上为主程序、R0_TIME(修改RAM中段码程序)、DESPLAY(数码管显示程序)、KS(按键查询程序)的流程图

3.主要模块设计思路及分析

(1)主程序模块

        在主程序中,有START和MAIN还有MAIN_LOOP三个部分。START用来初始化按键计数器(R0)和P口还有DPTR。MAIN用来调用R0_TIME (RAM中段码修改)。MAIN_LOOP调用数码管显示和轮询按键是否按下模块。按下则进行抖动消除,再次轮询。还按下,则查询键号,没有按下就回到MAIN_LOOP。

(2)键号查询模块

        当有按键按下时,需要查询键号。思路是:先初始化列好计数器(R4=0),点亮所有的行,和除了第一列的其他三列。逐行查询有无按键按下。如果没有就进行下一行检测,如果4行都没有,就换下一列(右移R2,R4+1),再次进行逐行检测。如果有按下,就将此行的首键号给A,并跳到KS进行键号计算(A+R4),计算后,检测按键是否松开,松开就将A出栈,并放回MAIN中调用R0_TIME(RAM中段码修改)。如果4列全部扫描完成,则回到MAIN_LOOP调用数码管显示和轮询按键是否按下模块。

(3)按键轮询模块

        将行全部设为高电平,列全部设为低电平(P1=F0H),然后读取P1的状态(其实是读取行线状态),如果有按键按下,则行线中会被短路为低电平。可以通过读取P1的状态,与F0H进行异或操作,如果结果为1,则有按键按下,如果为0,则无按键按下。

(4)数码管显示模块(延时模块)

        为了让数码管点亮与按键轮询同时实现,这里的延时模块可以进行数码管的显示。

        在此模块中,位选通过直接赋值来依次选择数码管(8~1),段选通过从RAM(30H~37H)来选择数字,给到P0口,点亮数码管。每显示一个数码管就延时一下再通过设定比较短的延时,利用人眼的视觉暂留,来实现8个数码管“同时点亮”的效果。

(5)RAM中数据修改模块

        如果R0为0,则还没有按键按下,则8个数码管需要全部显示0,所有RAM(30H~37H)中全部存9。如果R0等于1,则表示第一个按键按下,此时应该修改数码管8的段选所对应的RAM中的地址的值(30H),我们将求得的键号A存入30H中,后面的同理可得。         

三、 实现效果

以上为矩阵键盘输入实现显示后8为学号的实现效果。

四、源代码

// 矩阵按键:
//行:P1.7 P1.6 P1.5 P1.4	  1.7第0行
//列:P1.3 P1.2 P1.1 P1.0	  1.3第0列
//数码管:
//位选:P2.2 P2.3 P2.4
//段选:P0

    ORG 0000H
	LJMP START
	ORG 0100H
START:
    MOV P1, #0FFH		;初始化
	MOV P0, #0FFH
	MOV P2, #0H
	MOV DPTR, #TAB
	MOV R0, #0	        ;按下按键的次数, 用来控制数码管的点亮

MAIN:					   //初次检测
	LCALL R0_TIME
MAIN_LOOP:
	;如果r0没有修改,这无按下时,A=0,再次修改了30H中内存地址的值,所以数码管会一直显示1
	LCALL DESPLAY 
	LCALL KS
	JNZ K1				   //有按键按下,A=1。跳到K1进行消除抖动
	LJMP MAIN_LOOP
K1:						   //再次检测,消除抖动
	LCALL DESPLAY
	LCALL KS
	JNZ K2				   //有按键按下,跳到K2
	LJMP MAIN_LOOP			   //有按键按下,检查是哪一个按键按下
K2:
	INC R0			  ;按下次数加一
	MOV R2, #0F7H		   //列P1.3为0送入R2暂存
	MOV R4, #00H		   //列计数器
K3:
	MOV P1, R2
L0:
	JB P1.7, L1		       //P1.7(第0行)为1,无按键按下,跳到第一行检测
	MOV A, #00H			   //第0行的首键号给ACC
	LJMP LK				   //第0行按下,跳到键号计算程序
L1:
    JB P1.6, L2
	MOV A, #04H
	LJMP LK
L2:
 	JB P1.5, L3
	MOV A, #08H
	LJMP LK
L3:
	JB P1.4, NEXT		   //当前列的行都无按键按下,跳到下一列检测行
	MOV A, #0CH
LK:						   //键号计算程序
	ADD A, R4
	PUSH ACC
	LJMP K4
NEXT:
	INC R4
	MOV A, R2
	JNB ACC.0, MAIN_LOOP			//是否扫描完,扫描完,回到MAIN	//如果ACC的第7位是0,则跳转到标签MAIN指示的代码位置”。
	RR A					//循环右移,换下一列扫描
	MOV R2, A				//将ACC值送入R2暂存
	LJMP K3					//跳到K3继续
K4:						  //查看按键是否松开,松开则保存返回主程序
	LCALL KS
	JNZ K4
	POP ACC
	LJMP MAIN 
KS:
	MOV P1, #0F0H		   //列为0,行为1,如有按下,则行不全为1
	MOV A, P1			   //读行线状态,即高4位
	XRL A, #0F0H		   //两次状态进行异或操作,无按键按下,则A=0
	RET

DESPLAY:			   ;显示的同时,也是在延时 
LED8:
	MOV P2, #28
	MOV A, 30H
 	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
LED7:
    MOV P2, #24
	MOV A, 31H
	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
LED6:
    MOV P2, #20
	MOV A, 32H
	MOVC A, @A+DPTR
	MOV P0, A
    LCALL D10ms
LED5:
    MOV P2, #16
	MOV A, 33H
	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
LED4:
    MOV P2, #12
	MOV A, 34H
	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
LED3:
    MOV P2, #8
	MOV A, 35H
	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
LED2:
    MOV P2, #4
	MOV A, 36H
	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
LED1: 
    MOV P2, #0
	MOV A, 37H
	MOVC A, @A+DPTR
	MOV P0, A
	LCALL D10ms
    RET

R0_TIME:
	CJNE R0, #0, M1
M0:	
	MOV 30H, #9
	MOV 31H, #9
	MOV 32H, #9
	MOV 33H, #9
	MOV 34H, #9
	MOV 35H, #9
	MOV 36H, #9
	MOV 37H, #9
	AJMP FINISH
M1:	CJNE R0, #1, M2
  	MOV 30H, A
	AJMP FINISH
M2: CJNE R0, #2, M3
	MOV 31H, A
	AJMP FINISH
M3: CJNE R0, #3, M4
	MOV 32H, A
	AJMP FINISH
M4:	CJNE R0, #4, M5
	MOV 33H, A
	AJMP FINISH
M5:	CJNE R0, #5, M6
	MOV 34H, A
	AJMP FINISH
M6:	CJNE R0, #6, M7
	MOV 35H, A
	AJMP FINISH
M7:	CJNE R0, #7, M8
	MOV 36H, A
	AJMP FINISH
M8:	
	MOV 37H, A
FINISH:
	RET

D10ms:
    MOV R7, #40    ; 延时10ms子程序,采用双循环
D1:	MOV R6, #25
    DJNZ R6, $
    DJNZ R7, D1
    RET

TAB:
    DB 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH, 3FH  ; 共阴极 (1~0)

    END

五、总结与思考

本次实验学习和总结了一下关键点:

(1)外部中断触发的条件

由于INT0连接P3.2、INT1连接P3.3,所以原理上来说,只有K3(连接P3.2)和K3(连接P3.3)才可以触发中断。并不是任意按下一个按键就可以触发中断。(由于课本里面的代码,都没有将按键与中断请求源所联系,就直接可以触发中断,所以产生的疑惑)

(2)当寄存器不够用时,需要把数据存到哪里

由于寄存器是有限的,所有当我们需要存储很多数据时,只需要存到RAM中的内存即可。例如此实验中的8个数码管的段码。

(3)需要注意分支判断结果的跳回位置。

例如在此实验中,由于判断没有按键按下后,一直跳回MAIN,调用修改RAM中的值。因为A此时表示按键没有按下,所有为0,就修改了RAM中正确的段码。所有无按键按下时,需要跳回数码管显示,而不需要调用修改RAM中值的程序。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐