版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章输入/输出口综合应用5.1算术运算指令5.2键盘接口5.3数码管5.4设计课目与演练
——用P1口模拟SPI读写X25045小结
习题本章安排了MCS—51汇编指令体系中最复杂的部分——算术运算指令,到此,整个指令系统讲解完毕,同时也把程序设计的结构和要点全部给出。接下来,读者可以运用所有的程序和指令资源来设计、控制单片机的输入/输出了。因此,本章安排的实例和扩展也就相对丰富,而且都是比较重要的部分。本章涉及到的矩阵键盘和数码管的软硬件设计是单片机应用的基础,也是进一步学习的工具(可以让后续章节的实例可控制,可调试,看得见,摸得着),所以,读者要认真学习本章内容。5.1算术运算指令算术运算指令是8051系统中最复杂的部分。说它复杂,不仅因为指令的数量多,还因为很多指令要影响标志位。算术运算指令如表5-1所示。可从表5-1中进一步总结出操作码与操作数的组合关系,如图5-1所示。
加、减都是以A作为目标操作数。
立即寻址方式没有存储单元,不能进行自加、减的运算,其他寄存器寻址、寄存器间接寻址、直接寻址和累加器A都可以有INC、DEC的运算。
对DPTR寄存器的INC是唯一的16位加法。该寄存器没有DEC的操作。
MUL、DIV都需要A、B寄存器:在MUL中,乘法结果的高8位存放在B中,低8位存放在A中;在DIV中,除法的商存放在A中,余数存放在B中。
算术运算指令一般会影响到程序状态字PSW中的Cy、AC、OV、P标志位。但是加1、减1指令不影响。
这些指令共24条,可以完成加、减、乘、除等算术运算。其操作数都是8位无符号数,不能直接对有符号数和16位的数据进行运算。表5-1算术运算指令续表图5-1算术运算指令的各种组合5.1.1不带进位的加法指令不带进位的加法指令共有4条,如表5-1所示。这4条指令的功能是把A中的数与源操作数所指出的内容相加,结果存放在A中。对相关标志位的影响:
进位(借位)标志Cy:如果D7位向上有进位,则Cy=1;否则,Cy=0。
半进位标志AC:如果低4位向高4位有进位,则AC=1;否则,AC=0。
溢出标志OV:如果D7、D6只有一个向上有进位,则OV=1;否则,OV=0。即OV是D7和D6是否有进位的异或运算,关系表达式为:OV=CsCp。其中:Cs表示D7向Cy的进位;Cp表示D6向D7的进位。例如: MOV A,#67H
ADD A,#4AH其加法部分的执行过程如图5-2所示。该例完成的是4AH+67H,运算过程中,D3向D4位有进位,所以AC=1;D6向D7位有进位,所以Cp=1;D7向Cy位没有进位,所以Cs=0;因此OV=CsCp=01=1,即OV=1。运算结果中1的个数为4个,为偶数个,所以P=0。以后的加、减、乘、除的分析也是采用这种方法。另外,对于状态位的变化、观察和分析,仍然采用µV3的仿真功能进行检测。例如,上述程序段的运行可用如图5-3所示的窗口进行观察。读者要逐步熟悉这些方法,这对于进一步深入理解指令很有益处。图5-2不带进位的加法指令图5-3使用µV3调试窗口观察状态位的变化5.1.2带进位的加法指令带进位的加法指令共有4条,如表5-1所示。这4条指令的功能是把源操作数所指示的内容与累加器A中的内容相加,再加上进位标志Cy的值,结果存入A中。
运算结果对PSW中相关位的影响与加法指令“ADD”相同。注意:这里所指的进位标志位Cy的值,是该指令执行前Cy的值,而不是该指令执行过程中产生的进位标志值。
带进位的加法指令多用于多字节的加法。低字节相加时可能产生进位,高字节相加时,要考虑低位字节有可能向高位字节的进位,因此必须使用带进位的加法指令。例如:
MOV A,30H ADD A,32H MOV 34H,A
MOV A,#31H ADDC A,33H
MOV 35H,A该程序段的执行过程如图5-4所示。进一步分析:
该程序段完成的功能是双字节加法,把30H开始的两个字节与32H开始的两个字节求和,结果放在34H开始的两个字节内。
在分析图5-4时,要注意左、右两种加法指令的不同:ADD指令没有加Cy,而ADDC指令要加上Cy中的原有值。
另外还要注意分析对比,左、右两种加法运算中,地址有什么特点?如果在运算前把Cy清零(CLRC),那么左面的加法也可以使用ADDC。
然后再分析对比,是否可以使用循环的办法来完成多字节的加法呢?请读者尝试。图5-4带进位加法指令演示5.1.3带进位的减法指令带进位的减法指令共有4条,如表5-1所示。这4条指令的功能是把累加器A中的内容减去源操作数所指示的内容和Cy的值,把结果存入到A中。减法操作的实质是把减数转换为补码,然后再与被减数相加。所以,对于相关标志位的影响与前面的加法运算是相同的。这里直接采用二进制的减法来描述这种影响:
借位标志Cy:在减法运算中,如果D7位向上有借位,则Cy=1;否则,Cy=0。
半借位标志AC:在减法运算中,如果D3位向上有借位,则AC=1;否则,AC=0。
溢出标志OV:在减法运算中,如果D7、D6位只有一个向上有借位,则OV=1;否则,OV=0。这里,运算关系还是OV=CsCp。其中:Cs表示D7向Cy的借位;Cp表示D6向D7的借位。例如:
SETB C MOV A,#65H SUBB A,#0D7H CLR C MOV A,#65H SUBB A,#0D7H对这段程序的分析如图5-5所示。图5-5带进位的减法指令进一步分析:
由图5-5可以看出Cy的初始值对于结果的影响。所以,在执行减法时,如果不确定前面的操作对于Cy的影响,就要根据需要决定是否要先执行CLRC。
8051指令没有不带进位的减法指令。如果要执行不带进位的减法操作,则在执行减法前应该先执行CLRC。5.1.4加1、减1指令加1、减1指令如表5-1所示,加1指令5条,减1指令4条。这组指令的功能是将操作数所指示的单元中的内容加1或者减1,然后把结果送回到原操作单元。这组指令和C程序中的自加(++)、自减(--)有相似之处。其中,只有INCA和DECA指令会影响PSW中的P,其他的指令不影响任何标志位。
这组指令常用于循环控制变量的修改或需要对变量进行微调的场合,如地址的渐变,偏移量的增加等。
INCDPTR是唯一的16位加法指令,而且低8位的加法如果向上有进位,则进位操作不依赖于Cy(前面已经说不影响任何标志位)。
属于常用指令,不再单独举例,下面的程序中会频繁用到这组指令。5.1.5乘、除法指令乘、除法指令如表5-1所示,共有2条指令。这组指令的功能是把累加器A和寄存器B中的两个8位无符号整数做乘、除法运算,所得的结果存放在:乘法结果的低8位放在A中,高8位放在B中;除法结果的商放在A中,余数放在B中。
Cy位硬件清零。
乘法运算中,若乘积大于255(即B非0),则OV=1;否则,OV=0。除法运算中,B作除数。如果B为0,则除法无意义,这时OV=1;否则,OV=0。
奇偶标志位P只受A中1的个数影响,即:奇数个时,P=1;否则,P=0。
表5-1中的注释2(*2)所使用符号的意义如下:
(A)/(B)表示A中的数除以B中数的整除值,即商,这个值赋给A。
(A)%(B)表示A中的数除以B中数的余数,这个值赋给B。“/”、“%”这两个符号也是C程序中的运算符,这里作为描述符使用。汇编中对这两个符号没有定义。(高版本的汇编语言也开始支持一些运算表达式,具体请查看所使用编译程序的使用手册。)例如,执行下面的程序(后面给出了注释):
SETB C ;把Cy置1,为了后面观察乘、除法对Cy的影响
MOV A,#65H ;
MOV B,#0D7H;给A、B赋初值
MUL AB ;执行(A)×(B),结果为54D3H,有A=D3H,B=54H,Cy=0, ;OV=1,P=1;AC不受影响
INC A ;A中内容加1,此时A中值为D4H DEC B ;B中内容减1,此时B中值为53H DIV AB ;执行(A)÷(B),结果为: ;商为2赋给A,余数为2EH赋给B, ;Cy=0,OV=0;AC不受影响 ;具体的计算过程可以使用µV3的STEP进行观察5.1.6十进制调整指令十进制调整指令如表5-1所示。这条指令的功能是把累加器A参与BCD码加法运算所获得的8位结果(在累加器A中)进行修正,使之仍然为BCD码。
1. BCD码
BCD码就是采用4位二进制编码来表示1位十进制数。 4位二进制数的编码共有16个,即对应0000B~1111B,BCD码取其前10个编码来表示十进制的0~9,即编码为0000B~1001B,这种编码称为“8421BCD码”,简称为“BCD码”。这样一个字节可以存放两个BCD码(高4位和低4位各存放一个),这又称为压缩的BCD码。两个BCD码数据相加,结果也应当是BCD码,否则数据就会出错。上面的加法指令,对于4位二进制来说是逢16进1(进位),但是对于4位的BCD码而言,应当是逢10进1(进位)。这样,当执行加法指令且4位的运算结果超过9(介于10~15,即1010B~1111B)时,得到的就不是BCD码了,这时就出现了错误。因而,要对运算结果进行修正,即进行十进制修正,才可以得到正确的BCD码。
2. BCD码修正进行BCD码修正的目标是把4位二进制的十六进制修改为BCD码的十进制。因此,如果检测到4位的运算结果超过9或者向上有进位(超过15),就应该把结果进行修正。根据前面的加法指令知:如果低4位有进位,则AC=1;如果高4位有进位,则Cy=1。因而,需要进行BCD码修正的检测判断依据有3个:AC、Cy是否为1,4位二进制值是否大于9。图5-6所示的运算可以让读者明白为什么要进行BCD码的修正以及怎样修正。图5-6BCD码的调整进一步分析:
由图5-6中可以看出,如果得到的结果不是正确的BCD码,则可以通过把这个4位加0110B(即加6)的方法得到正确的结果。这就是DAA指令所做的。
只有得到的结果不是正确的BCD码时,才采用图中的方式进行调整,如图5-6(a)、(b)所示。但如果已经得到了正确的BCD码,则不需要调整了。DAA的调整逻辑如图5-7所示。这个判断是由硬件完成的,我们只要使用DAA指令就可以了。
十进制调整指令只能跟在加法指令的后面,对A中的数据进行调整。但51系列单片机没有十进制减法调整指令。如果需要,就只能按照补码的方式来转换为加法运算了。思考题:编写一段程序来模拟DAA指令的执行和功能。图5-7BCD码调整流程5.2键盘接口第3章已经介绍了独立式按键的设计,这里讲行列式按键的设计。完整的按键设计方案还要加上第6章的中断式设计。独立式按键电路的每一个按键开关占一根I/O口线,当按键较多时,要占用比较多的口线,因此通常采用行列式按键。行列式按键如图5-8所示,按键放在行与列的交叉点上形成键盘矩阵,因此这种方式又称为矩阵式按键。图5-8行列式按键行列式键盘在使用时将行线通过上拉电阻接VCC(如图5-9所示),如果此时无任何按键按下,则对应的行线输出为高;如果此时有按键按下,则对应交叉点的行线和列线短接,行线的输出此时依赖于对应交叉点列线的电平,这样就可以判断按键是否按下并进而识别按键。实际应用中,一般将Row0~Row3和Col0~Col3接到8位单片机P1口上,在程序中分别对行线和列线进行不同的操作,就可以确定按键并给出编码。注:行线这里指Row0、Row1等,列线这里指Col0、Col1等。下面讲解4*4按键的设计。按工作方式,行列式键盘有扫描法、线反转法、中断法三种,前两种的电路分别如图5-9(a)、(b)所示(中断法的电路图见第6章)。图5-9行列式键盘的工作原理5.2.1扫描法行列式键盘扫描法的工作原理如图5-9(a)所示。其基本工作原理和步骤为:
(1)初始化。把行线置高,转为输入状态;把列线全部置低,输出0。指令为:
MOVP1,#0FH。
(2)判断按键。循环读入P1的值,分析行线状态,如果全为“1”,则没有按键按下;如果有“0”出现,则表示有按键按下。
(3)软件去抖。第一次判断到有按键后,延时10ms,再次判断键盘的状态,如果仍然有“0”出现,则可以确定有按键按下;否则,是按键的抖动或者干扰。
(4)识别按键(按键编码)。先令列线Col0为“0”,其余三根列线为“1”,读取Row0~Row3的状态。如果有“0”出现,那么其中为低电平的Row.x与当前Col0交叉点的按键按下,这样便确定了按键的位置,同时也可以将这个按键编码为(Row.x,Col0)。如果没有“0”出现,那么再令Col1为“0”,其余三根列线为“1”,读取Row0~Row3的状态。如果有“0”出现,那么其中为低电平的Row.x与当前的Col1交叉点的按键按下,这样便确定了按键的位置,同时也可以将这个按键编码为(Row.x,Col1)。如果没有“0”出现,依次令Col2、Col3为“0”,按照同样的方法进行按键的识别和编码。这样,就可以得到按键的编码为(Row.x,Col.y)。x、y的取值范围都是0~3。
(5)重键和连续按键。重键在单片机中是必须妥善处理的一个问题。由于单片机的处理速度较快,上述过程只需要十几或者几十毫秒,而一般的手动按键由按下到松开需要几百毫秒到几秒,这样会导致单片机对一次按键响应好几次的后果。由第3章的按键曲线图(图3-18)可知,这个不好掌握的按键时间恰恰发生在稳定接触的中间位置上,这样只要增加按键是否释放的判断就可以准确地定义一次按键操作了。如果我们要增加连续按键的功能,应该借助于另外一个概念:定时/计数器。当然,也可以使用循环的功能。但是在单片机中为什么要抛弃它本身具有的功能呢?还是等到下一章学习了定时/计数功能后再来完成连续按键这样的功能吧。当然你可以尝试使用Delay子程序来完成上述的功能。思路:每个Delay都进行一次按键的判断;如果连续按键超过n(n需要自定义)个Delay,就认为重新按键一次。
(6)按键处理。这是非常完善的按键处理子程序,源程序如下:
MOVP1,#0FH ;按键接口初始化
LOOP: LCALLKEY_TEST ;检测按键
CJNE R0,#00H,FUNC ;如果有按键,则处理
SJMP LOOP ;重复检测
FUNC: ;这里的功能为空,请自己补充
RET
DEL10: ;这里的延时为空,请自己补充
RET
KEY_TEST: ;键盘检测的子程序的入口地址
MOV R0,#00H ; R0存放按键编码,初始化为0,;表示无按键
MOV A,P1 ;读入按键的状态
ANL A,#0FH ;屏蔽掉列线状态
CJNE A,#0FH,RE_TEST ;判断行线状态是否全为“1”,如果不是,去抖动
SJMP RETU ;如果全部为“1”,则无按键,转去返回处理
RE_TEST: ;去抖动处理
LCALL DEL10 ;延时10ms MOV A,P1 ;再读入按键口状态
ANL A,#0FH ;屏蔽掉列线状态
CJNE A,#0FH,KEY_CODE ;再次判断是否还有按键,如有,转去得到键码
SJMP RETU ;否则,说明是抖动或者干扰
KEY_CODE: ;在这里得到键盘编码,确定按键
MOV R1,#04H ;需要循环检测4次(因为有4条列线) MOV R2,#10H ;初始化列线检测输出数值,取反后仅有一条列线为0
KEY_SCAN: ;进入键码扫描
MOV A,R2 ;把R2的值适当变换后输出,变成列扫描码
CPL A ;一次只有一列为0,其余的列都为“1” MOV P1,A MOV A,P1 ;再读入按键状态
ANL A,#0FH ;判断当前为0的列线上是否有按键
CJNE A,#0FH,KEY_GET;如果有,去生成键码
MOV A,R2 ;否则,重新组织下一次的扫描
RL A ;把列扫描码修改,变成下一列对应为0,
MOV R2,A ;其余的全为“1” DJNZ R1,KEY_SCAN ;判断4列是否已经全部扫描,若没有,则继续扫描
SJMP RETU ;如果全部扫描完毕,则跳转到返回点
KEY_GET: ;在这里组织生成键码
CPL A ;取反后,对应按键的那个行为“1”,低4位
ORL A,R2 ; R2中,对应按键的那个列为“1”,高4位
MOV R0,A ;二者合起来后得到的就是按键的编码
RETU: ;返回主程序,这是本子程序的唯一出口
RET按键检测程序段的执行流程图如图5-10所示。图5-10按键子程序流程图5.2.2线反转法扫描法需要逐列扫描查询,根据按键所在位置的不同,每次查询的次数也不相同。如果按键的位置在最后一列,则要经过最多次数的查询才能获得该键码。相比而言,线反转法只需要固定的两次扫描即可得到键码。行列式键盘线反转法的电路如图5-9(b)所示。其工作原理和步骤为:
(1)将行线作为输出,列线作为输入,行线输出全“0”,读入列线。如果读入各位全为“1”,则没有按键按下;否则,列线中为“0”的位对应按键所在的列。
(2)延时10ms。
(3)反过来,将行线作为输入,列线作为输出,列线输出全“0”,读入行线。如果读入各位全部为“1”,则没有按键按下;否则,行线中为“0”的位对应该按键所在的行。
(4)这样就得到了行、列位置,同时也得到了键盘编码。仍然给出源程序,请读者对照分析:
MOV P1,#0F0H ;按键接口初始化,行输出,列输入
LOOP: LCALL KEY_TEST ;检测按键
CJNE R0,#00H,FUNC ;如果有按键,则处理
SJMP LOOP ;重复检测
FUNC: ;这里的功能为空,请自己补充
RET
DEL10: ;这里的延时为空,请自己补充
RET
KEY_TEST: ;键盘检测的子程序的入口地址
MOV R0,#00H ; R0存放按键编码,初始化为0,表示无按键
MOV A,P1 ;行输出,读入列的状态
ANL A,#0F0H ;屏蔽掉行线状态
CJNE A,#0F0H,RE_TEST;判断列线状态是否全为“1”,
;如果不是,去抖动
SJMP RETU ;如果全部为“1”,则无按键,转去返回处理
RE_TEST: ;去抖动处理
LCALLDEL10 ;延时10ms MOV R0,A ;先保存刚才的列位置
MOV P1,#0FH ;交换,行输入,列输出
MOV A,P1
;再读入按键行状态
ANL A,#0FH
;屏蔽掉列线状态
CJNE A,#0FH,KEY_CODE;再次判断是否仍然还有按键如有,转去得到键码
SJMP RETU
;否则,说明是抖动或者干扰
KEY_CODE:
;在这里得到键盘编码,确定按键
ORL A,R0
;把行列状态合并,得到键码
XCH A,R0
;把键码交换到R0
RETU: MOV P1,#0F0H
;恢复行输出,列输入的状态
RET
;返回主程序请读者自己画出流程图。可以看出,这种方法要比扫描法简单、高效。5.3数码管经单片机处理后的数据需要显示,同时人机接口也需要进行显示。目前,在单片机系统中最常用的显示器有发光二极管显示器(LED)和液晶显示器(LCD)。前者成本低廉,使用简便,但是只能显示数字或特定的字符;后者价格稍高,使用也相对复杂,但是功能强大,汉字、图形、图表都可以显示。正是由于LCD使用的复杂及其功能的强大,把它放在第12章专门进行讲述。数码管的应用非常普遍。在北京“鸟巢”体育场,伴随着几万人的同声倒计时,迎来了奥运会开幕式,而里面摆出的9、8、7、…、0的造型就是常用的数码管显示图案。5.3.1LED显示器的结构与工作原理
LED(LightEmittingDiode)显示器的基本组成部分是发光二极管。把若干个发光二极管组合起来排列成如图5-11所示的阵列,并且给这些发光二极管编号为a、b、c、d、e、f、g,共7个。每个二极管代表字符中的一个笔画,需要显示某个字符时,就将对应的笔画点亮。这种显示器件称为7段数码管。当需要显示小数点时,可增加一个圆点状的二极管dp,所以,有时也称为8段数码管。数码管里面发光二极管的接线方式有两种,如图5-12(a)、(c)所示,分别称之为共阳极、共阴极接法。其对应的数码管的引脚配置分别如图5-12(b)、(d)所示。图5-11发光二极管图案图5-127段数码管的引脚及接线方式由于7段数码管加上小数点dp,共有8个发光二极管,组成一个8位的字节,从而正好方便和单片机的一个并口进行接口,只要控制相应位电平的高低,就可以控制数码管显示相应的字符。把这个控制字节称之为段码。按照图5-13所示的对应关系,就可以得到共阳极接法和共阴极接法时显示字符与控制段码的对应关系,如图5-14所示。图5-13笔画与字节的位对应关系图5-14数码管的控制段码与显示字符的对应关系5.3.2驱动电路设计
1.单管驱动单管驱动是最简单的使用方式。其电路如图5-15所示。
直接使用P1口驱动,因为端口的低电平驱动能力强,所以采用了共阳极数码管。如果选用共阴极数码管,则可按照第4章介绍的方式进行驱动(不推荐),后面有使用了集成电路的驱动方式。
从图5-12所示数码管的内部结构可以看出,里面没有限流电阻,使用时,要在外面附加限流电阻。图5-15中的R2~R9就是限流电阻。具体的电阻值可以根据环境要求和所选元器件的参数进行调整,图中参数仅供参考。
利用P1口输出相应的段码,就会有相应字符的显示。图5-15数码管单管驱动方式显示示例程序如下:
MOV DPTR,#TABLE ; DPTR指向后面的数据表
MOV R0,#00H ;用R0里面的值作为表格中具体数据的指针
LOOP: ;或者作为偏移量来理解
MOV A,R0 ;把偏移量赋给偏移指针A MOVC A,@A+DPTR ;查表,取出对应0~9的段码
MOV P1,A ;输出,这个时候对应字符显示
LCALLDELAY ;延时,否则速度变化太快而无法识别字符
INC R0 ;修改偏移量,指向下一个
CJNE R0,#10H,LOOP ;一共16个字符段码,超过后从头再来
MOV R0,#00H ;重新赋值为0 SJMP LOOP ;继续进行下一个字符的显示
DELAY: ;延时,稍微复杂了一些,仔细研究
MOV R1,#6H ;第一层循环控制变量R1
DELAY1:
MOV R2,#00H ;第二层循环控制变量R2
DELAY2:
MOV R3,#00H ;第三层循环控制变量R3
DJNZ
R3,$
;延时子程序在移植前,一定要研究后再使用
DJNZ
R2,DELAY2 ;环境里面,已经使用了哪些寄存器
DJNZ R1,DELAY1 ;原则是不能影响主程序,不能发生冲突
RET ;返回
TABLE: DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H ;012345 67
DB 80H, 90H, 88H,83H, 0C6H,0A1H,86H,8EH
;
89A BCD E F
这个程序段完成的功能就是循环显示0~F。读者可以在这个基础上进行修改,比如让数据的显示顺序为9、8、7、…、1、0。思考:如果把数码管变成共阴极的,应怎么修改?上面的程序中使用了DB伪指令和MOVCA,@A+DPTR查表指令。
1)定义字节伪指令DB格式:[标号:]
DB8位字节数据表数据表可以是二进制、十进制、ASCII码或者字符串等,数据之间用“,”隔开。功能:从标号指定的地址单元开始,将数据表中的数据按顺序依次连续存放其中。例如:ORG1234H
TABLE:DB00H,36H,82H
DB'A'
DATA1:DB00101101B,12,"Lo"
DB"ve"伪指令DB定义的数据在存储器中的存储状态如图5-16所示。类似的伪指令还有DW。不过,它后面跟的都是字数据,即16位的数据,单字节数据也会按字存储。例如:
ORG1234H
TABLE: DB01H
DW'A'
DW2123H伪指令DW定义的数据在存储器中的存储状态如图5-17所示。图5-16伪指令DB定义的数据图5-17伪指令DW定义的数据
2)查表指令MOVCA,@A+DPTR在指令部分已经讲解了该指令的使用方法,这里进一步分析利用该指令设计查表的方法。本节中的例程要把存放在表格中的0~F的显示段码依次取出,送给P1去输出控制数码管显示数据。在前面的显示示例程序中,DPTR已经指向存放段码的表格的头地址(首地址,即表格开始单元的地址)。只要把A作为偏移量,变化范围在0~15内,就可以依次取出表格中存放的段码。思考:如果表格中存放的数据是16位的子程序的地址,我们该怎样使用呢?比如:DWPROG1、PROG2、PROG3、…、PROGn(后面会有这样的例程)。
2.多管驱动图5-15中的单管使用P1口直接驱动。如果是两管,按照上面的方法,我们需要使用两个并口,比如P1口、P2口;如果是三管,则可以使用P0、P1、P2;如果是4管,则要使用P0、P1、P2、P3全部并口资源了。实际上这种方法就是图5-15中单管驱动方式的扩展,仍然是一个数码管对应一个端口。这样,驱动的数码管越多,留给其他操作的资源就越少;而且,当数码管超过4个时,这种方法已失去意义了。以两个数码管为例,电路如图5-18所示。图5-18数码管的双管驱动这时,驱动哪个数码管,只要向相应的端口写对应的段码即可,而且两个数码管之间没有影响。只要不改变数码管显示的字符,该数码管上的驱动段码是恒定的,不需要改变;只有显示字符需要改变,才会改变相应数码管上的段码。这种数码管的显示方式称为静态显示方式。静态是相对于动态而言的,那么什么是动态显示方式呢?上面提到的静态显示方式的明显缺点是:当数码管较多时,需要很多的I/O口线,而且当数码管超过4个时已经无能为力了。虽然,我们可以通过外扩RAM地址空间的方式来扩展静态显示方式的能力,但是硬件资源的浪费非常大。所以,当驱动数码管较多时,可采用另一种方式——动态扫描。当风扇高速旋转时,可看到几片扇叶?电视里面的图像不是连续的,而是一幅一幅的,说详细点是一行一行的,再进一步微观是一个点一个点显示的,但是我们看到的却是连续的完整的画面,这是为什么?视角暂留现象。我们也可以利用这个原理来设计数码管的显示。事实上,1.6节中控制发光二极管闪烁的演练中已经观察到这样的现象,如果显示没有延时或者延时太短,则变化速度太快,看不到闪烁效果。这个现象的形成也是这个原理。动态显示原理电路如图5-19所示。图5-19数码管动态显示原理现在,8位数码管全部并联到P1口,当P1口输出段码时,哪个数码管亮就决定于上面的开关控制了。P2口通过PNP三极管来控制数码管的供电,输出高电平时停电,输出低电平时供电。现在做如下的操作:当P1口送出0的段码时,P2.0置低,其余位置高,这时只有Q0显示0;当P1口送出1的段码时,P2.1置低,其余位置高,这时只有Q1显示1;…;当P1口送出7的段码时,给P2口输出7FH,即只有P2.7置低,其余位置高,这时只有Q7显示7;然后,当P1口送出0的段码时,给P2口输出FEH,即只有P2.0置低,其余位置高,这个时候只有Q0点亮显示0;然后依此类推,进入循环。可以看出,P1口不停地在输出数据,但是数据并不是在同一个数码管上显示,而是由上面的P2口控制哪位数码管点亮显示。这里采用的方式是依次点亮,这样Q0、Q1、Q2、…、Q78个数码管不是同时显示的,而是逐个显示0、1、2、…、7。数码管全部显示一遍所用的时间称为一个扫描周期。如果这个周期为T = 1s(对应的频率就是1Hz)甚至更长,则可以看到的效果就是Q0上显示0,T/8s后Q1上显示1,…,满一个周期时,Q7点亮显示7,然后进入下一个周期。现在逐渐提高这个扫描频率到25Hz左右时,就会发现所有的数码管都在亮,上面显示的数据顺序就是7、6、5、4、3、2、1、0。(为什么是25Hz?你可以试验,事实上应当更高一些,会更清晰)。好了,显示成功。显示其他的数据呢?对应输出段码就可以了。现在应该明白所谓的“动态”了吧!每一位数码管都不是在持续显示,而是在不断地按顺序亮灭,单片机也在不断地对这些数码管逐位进行扫描,只是由于速度快,看起来是所有的数码管在同时显示。这就是动态扫描的显示方式。现在要求Q1、Q0最低的2位数码管循环显示00~99,其余的都不点亮,数字变化频率为1Hz。源程序如下:
ORG0100H
NUM
EQU
40H
;计数单元,要显示的数据BCD码形式
UNITS
EQU
41H
;存放需要显示的个位数
TENS
EQU
42H
;存放需要显示的十位数
COUNTER
EQU
50H
;存放循环次数控制量
START: MOVNUM,#00H;显示初始值00,然后开始加1显示
LOOP1:
;这层循环是控制显示数据变化频率为1Hz MOVCOUNTER,#60H ;循环控制
LOOP2: ;这层循环是控制扫描每个数码管
;保证每个的显示频率在25Hz以上
LCALLCONVERT ;把预显示的数据分解为个位和十位数存放
LCALLDISPLAY ;显示数据后有个延时,调节这个延时可以改变数码管扫描频率
DJNZCOUNTER,LOOP2 MOVA,NUM ;这里要加1显示数据
INCA ;因为是BCD码格式,所以要传输到A中操作
DAA MOVNUM,A LJMPLOOP1CONVERT: MOVA,NUM ; NUM中存放的是要显示的BCD码格式的数据
ANLA,#0FH ;把低位BCD码放到UNITS,个位存储单元
MOVUNITS,A MOVA,NUM ;把高位BCD码放到TENS,十位存储单元
ANLA,#0F0H SWAPA MOVTENS,A
RET
DISPLAY: MOVDPTR,#TABLE ;存放0~9的段码表格的首地址
MOVA,TENS ;取十位数上的数据对应的段码
MOVCA,@A+DPTR MOVP2,#0FFH ;在改变原来显示数据前,要先关闭数码管
MOVP1,A ;输出段码
MOVP2,#0FDH ;开数码管Q1 LCALLDELAY10 MOVA,UNITS ;取个位数上的数据对应的段码
MOVCA,@A+DPTR ; MOVP2,#0FFH ;关闭数码管
MOVP1,A ;输出段码
MOVP2,#0FEH ;开数码管Q0 LCALLDELAY10 RET
DELAY10: MOVR0,#66
DEL1: MOVR1,#00H
DEL2: MOVR2,#00H DJNZR2,$
DJNZR1,DEL2 DJNZR0,DEL1 RET
TABLE: DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H进一步解释:
伪指令EQU:赋值伪指令。格式:字符名称EQU数据或者汇编符号功能:将一个特定的汇编符号或者一个数据赋予规定的字符名称。这里使用的“字符名称”不是标号,不能用“:”来做分隔符。用EQU指令赋值以后的字符名称可以用作数据地址、代码地址、位地址或者当作一个立即数来使用。这个字符名称不能与汇编语言的关键字同名。如:TEMPEQUA
DATA1EQU68H
MOVTEMP,#DATA1
伪指令DATA:与EQU有些相似。格式:字符名称DATA表达式功能:将数据地址或代码地址赋予规定的字符名称。
DATA指令与EQU指令的区别:
(1) EQU指令必须先定义后使用,而DATA则无此限制。因此,EQU通常放在程序的开头,而DATA指令既可以放在源程序的开头,也可放在末尾。
(2) EQU指令可以把一个汇编符号赋给一个字符名称(如上例:TEMPEQUA),而DATA伪指令不行。
(3) DATA伪指令可将一个表达式的值赋给一个字符变量,所定义的字符变量也可以出现在表达式中,而EQU定义的字符则不能这样使用。DATA伪指令在程序中常用来定义数据地址。如:
NUMDATA35H
MOVA,NUM
这个程序的关键是CONVERT子程序和DISPLAY子程序。控制1Hz的外围循环变量可以根据实验情况进行调整。控制数码管扫描速度的变量存放在NUM中,也可以根据实验情况进行修正。进一步:读者可以根据这个程序进一步加大难度,比如配合键盘显示十进制、十六进制的键码等。5.4设计课目与演练——用P1口模拟SPI读写X25045
X25045是串行EEPROM,它将四种功能集于一体:上电复位控制、看门狗定时器、降压管理以及块保护功能。它有助于简化应用系统的设计,减少印制板的占用面积,提高可靠性。该芯片内的EEPROM是具有Xicon公司块锁保护的CMOS串行EEPROM,被组织成8位的结构。它由一个由四线构成的SPI总线方式进行操作。其擦写周期至少有10000次,并且写好的数据能够保存100年。对于该芯片的详细情况请参阅DATASHEET。
X25045与8051单片机的接口电路如图5-20所示。图5-20X25045的管脚配置及与8051的接口按照连接电路,做出如下的定义:
CS EQU P1.0
SO EQU P1.1
SI EQU P1.2
SCK EQU P1.3下面给出访问及设置X25045的子程序。应用这些子程序,完成下面的要求:在8051内部RAM中从30H开始的10个单元内有一些重要的参数,把这些参数保存到X25045内部。进一步:要求8051开机后,从X25045中取出这些参数并放置到内部RAM中从30H开始的连续10个单元中。参考:
设置写使能锁存器
----------------------------
WREN:
CLR SCK CLR CS MOV A,#COMMAND LCALLOUT CLR SCK SETB CS RET
----------------------------
复位写使能锁存器
----------------------------
WRDI: CLR SCK CLR CS MOV A,#COMMAND LCALL OUT CLR SCK SETB CS RET
----------------------------
写状态寄存器
----------------------------
WRSR: CLR SCK CLR CS MOV A,#COMMAND LCALL OUT CLR SCK SETB CS LCALL POLL RET
----------------------------
读状态寄存器
----------------------------
RDSR: CLR SCK CLR CS MOV A,#COMMAND LCALL OUT LCALL IN CLR SCK SETB CS RET
----------------------------
写字节
----------------------------
WRITE: MOV DPTR,#ADDR CLR SCK CLR CS MOV A,#COMMAND MOV B,DPH MOV C,B.0 MOV ACC.3,C LCALL OUT MOV A,DPL LCALL OUT MOV A,#BYTE_DATA LCALL OUT CLR SCK SETB CS LCALL POLL RET
-
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 果蔬加工设备租赁服务合同
- 2026年气象灾害防御培训总结发言稿
- 电脑编程培训合同
- 导游服务合同范本样本2026
- 2026年行政问题自动应答机器人
- 书道馆2026年书法艺术鉴赏活动协议
- 2026年幼儿园安全管理制度学习讲稿
- 2026年加油站新员工入职安全培训
- 生态化生态保护补偿协议
- 2026年舞蹈工作室店长市场推广与引流培训
- 《2和5的倍数的特征》课件(省一等奖)
- 2023年度上海市教师招聘考试《中学生物》押题卷(含答案)
- 滨州科技职业学院辅导员考试题库
- 教师因两地分居调动工作申请书
- 游岳阳楼记带翻译
- GB/T 10592-2023高低温试验箱技术条件
- CB马达安装维护手册中文
- 2023年道县小升初英语考试题库及答案解析
- JJG 693-2011可燃气体检测报警器
- JJG 1148-2018电动汽车交流充电桩
- GB/T 18707.1-2002机械振动评价车辆座椅振动的实验室方法第1部分:基本要求
评论
0/150
提交评论