您的位置:首页 > 其它

基于Proteus+8051汇编应用实例系列之五--数码管显示拨码开关编码

2013-01-05 17:30 309 查看
题目描述:

Proteus仿真图如下所示:



通过一个拨码开关来生成一个数,并通过4位数码管以十进制方式显示出来,其中拨码开关与P1口连接,P0口通过一个74LS245来与数码管相连(因为P9口自身的高电平不足以驱动数码管,需要这个器件来帮忙),段选连接到P2口的低四位上。

问题分析:

1)拨码开关因每一位的开关状态,构成一个有8个二进制位的字节,即读取P1口的数值也就是拨码开关的状态

2)将P1口的数值读回来,是以16进制(实质当然还是8个二进制)表示,需要将它转换成三位的十进制数显示在数码管上,通过除以10,余数为个位数,然后再除以10,余数是十位,商是百位数。

3)多位数码管的动态扫描显示,即通过段选指定显示第几个数字,通过引脚将相应信号传入,并保留一个很短的时间段,然后将所以段选再关闭(称作消隐过程),以显示下一位数字。注意这种动态扫描,就是一位一位地显示,在间隔够短时,人眼看到的便是三位同时显示的效果了。另外注意消隐过程,若无消除,当各位显示间隔较大时,出现流动显示的效果,间隔够短时,便显示乱码了,可能每一位都显示不正常了。

代码文件main.asm

// *************************************************************
//	数码管显示拨码开关编码
// 1)多位数码管的动态扫描显示(通过段选来指定位置)
// 2) 16进制转换成三位的十进制数(DIV指令)
// *************************************************************
ORG	00H
// *************************************************************
// 初始化状态
// *************************************************************
START:
MOV A,#0FFH
MOV P1,A
// *************************************************************
// 主循环
// 不辞辛苦地读取拨码开关的值,并通过DIV指令,得出对应三位十进制数的个、十、百位数值
// *************************************************************

MAIN_LOOP:
MOV A,P1	//重新读取拨码开关值,即P1口
//取个位数,并保存到R1
MOV B,#10
DIV AB
MOV R1,B	//个位数存在R1中
//取十位数,并保存到R2
MOV B,#10
DIV AB
MOV R2,B
//取百位数,并保存到R3
MOV B,#10
DIV AB
MOV R3,B

CALL SHOW_NUM

JMP	MAIN_LOOP
// *************************************************************
// 显示十进制数
// 1)显示百、十、个位时依次关联,以方便实现从百位或从十位开始显示
// 2)当百位数不为零时,从百位开始显示,若百位为零,十位不为零,则从十位开始显示,个位始终显示
// *************************************************************

SHOW_NUM:
//R3不为零时,显示百位数
CJNE	R3,#0,SHOW_BAI_WEI

//R2不为零时,显示十位数
CJNE	R2,#0,SHOW_SHI_WEI
JMP	SHOW_GE_WEI
RET
// *************************************************************
// 显示个位,结束数字显示过程,用RET返回
// *************************************************************
SHOW_GE_WEI:
//R1个位显示
MOV A,R1
MOV DPTR,#NTABLE
MOVC A,@A+DPTR

MOV P0,A
MOV P2,#07H
CALL DELAY
MOV P2,#0FH		//消隐过程,在短暂的时间显示后,要关掉所有段选,以便显示其它位,否则会干扰其它位而造成显示乱码
RET
// *************************************************************
// 显示十位,后续跳转到个位的显示过程
// *************************************************************
SHOW_SHI_WEI:
MOV A,R2
MOV DPTR,#NTABLE
MOVC A,@A+DPTR
MOV P0,A
MOV P2,#0BH
CALL DELAY
MOV P2,#0FH		//消隐,关掉所有段选(置1)
JMP	SHOW_GE_WEI
// *************************************************************
// 显示百位,后续跳转到十位的显示过程
// *************************************************************
SHOW_BAI_WEI:
MOV A,R3
MOV DPTR,#NTABLE
MOVC A,@A+DPTR
MOV P0,A
MOV P2,#0DH
CALL DELAY
MOV P2,#0FH   //消隐,关闭所有段选(置1)
JMP	SHOW_SHI_WEI

;; 数码管显示编码表
NTABLE:	DB	 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ,77H,7CH,39H,5EH,79H,71H,76H

// *************************************************************
// 短暂的延时,以方便显示数码管,给相应引脚信号后,要保持一会儿
// *************************************************************

DELAY:
MOV R5,#1
D1:		MOV R6,#20
D2:		MOV R7,#248
DJNZ	R7,$
DJNZ	R6,D2
DJNZ	R5,D1
RET

END


注:

1) 18~35行:主循环,完成不断读取P1口的值,以便后面对它进行处理,得出个,十,百位上的数值(此处用到了DIV指令,运算结果是余数放B,商放A中)

2)42~87行:完成显示数字,注意这种逻辑结果,将显示百、十、个位数分别加标签分隔,并依次关联起来,以满足从百位还是从十位开始显示的情况。

3)数码管编码的使用,借用了数据表的形式,将各位上的数巧妙转换为相应的编码输送给数码管的相应位。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐