单片机教学(十五)
位及位操作指令通过前面那些流水灯的例子,我们已经习惯了“位”一位就是一盏灯的亮和灭,而我们学的指令却全都是用“字节”来介绍的:字节的移动、加法、减法、逻辑运算、移位等等。用字节来处理一些数学问题,比如说:控制冰箱的温度、电视的音量等等很直观,可以直接用数值来表在。可是如果用它来控制一些开关的打开和合上,灯的亮和灭,就有些不直接了,记得我们上次课上的流水灯的例子吗?我们知道送往 P1 口的数值后并不能马上知道哪个灯亮和来灭,而是要化成二进制才知道。
工业中有很多场合需要处理这类开关输出,继电器吸合,用字节来处理就显示有些麻烦,所以在 8031 单片机中特意引入一个位处理机制。位寻址区在 8031 中,有一部份 RAM 和一部份 SFR 是具有位寻址功能的,也就是说这些 RAM 的每一个位都有自已的地址,可以直接用这个地址来对此进行操作。字节地址位地址图 1 内部 RAM 的 20H-2FH 这 16 个字节,就是 8031 的位寻址区。看图 1。可见这里面的每一个 RAM 中的每个位我们都可能直接用位地址来找到它们,而不必用字节地址,然后再用逻辑指令的方式。
可以位寻址的特殊功能寄存器 8031 中有一些 SFR 是可以进行位寻址的,这些 SFR 的特点是其字节地址均可被 8 整除,如 A 累加器,B 寄存器、PSW、IP(中断优先级控制寄存器)、IE(中断允许控制寄存器)、SCON(串行口控制寄存器)、TCON(定时器/计数器控制寄存器)、P0-P3(I/O 端口锁存器)。以上的一些 SFR 我们还不熟,等我们讲解相关内容时再作详细解释。位操作指令 MCS-51 单片机的硬件结构中,有一个位处理器(又称布尔处理器),它有一套位变量处理的指令集。
在进行位处理时,CY(就是我们前面讲的进位位)称“位累加器”。有自已的位 RAM,也就是我们刚讲的内部 RAM 的 20H-2FH 这 16 个字节单元即 128 个位单元,还有自已的位 I/O 空间(即 P0.0…..P0.7,P1.0…….P1.7,P2.0……..P2.7,P3.0……..P3.7)。当然在物理实体上它们与原来的以字节寻址用的 RAM,及端口是完全相同的,或者说这些 RAM 及端口都可以有两种用法。
位传送指令 MOV C,BITMOV BIT,C 这组指令的功能是实现位累加器(CY)和其它位地址之间的数据传递。例:MOV P1.0,CY ;将 CY 中的状态送到 P1.0 引脚上去(如果是做算术运算,我们就可以通过观察知道现在 CY 是多少啦)。MOV P1.0,CY ;将 P1.0 的状态送给 CY。位修正指令位清 0 指令 CLR C ;使 CY=0CLR bit ;使指令的位地址等于 0。例:CLR P1.0 ;即使 P1.0 变为 0 位置 1 指令 SETB C ;使 CY=1SETB bit ;使指定的位地址等于 1。
例:SETB P1.0 ;使 P.0 变为 1 位取反指令 CPL C ;使 CY 等于原来的相反的值,由 1 变为 0,由 0 变为 1。CPL bit ;使指定的位的值等于原来相反的值,由 0 变为 1,由 1 变为 0。例:CPL P1.0 以我们做过的实验为例,如果原来灯是亮的,则执行本指令后灯灭,反之原来灯是灭的,执行本指令后灯亮。位逻辑运算指令位与指令 ANL C,bit ;CY 与指定的位地址的值相与,结果送回 CYANL C,/bit ;先将指定的位地址中的值取出后取反,再和 CY 相与,结果送回 CY,但注意,指定的位地址中的值本身并不发生变化。
例:ANL C,/P1.0 设执行本指令前,CY=1,P1.0 等于 1(灯灭),则执行完本指令后 CY=0,而 P1.0 也是等于 1。可用下列程序验证:ORG 0000HAJMP STARTORG 30HSTART: MOV SP,#5FHMOV P1,#0FFHSETB CANL C,/P1.0MOV P1.1,C ;将做完的结果送 P1.1,结果应当是 P1.1 上的灯亮,而 P1.0 上的灯还是不亮。
位或指令 ORL C,bitORL C,/bit 这个的功能大家自行分析吧,然后对照上面的例程,编一个验证程序,看看你相得对吗?位条件转移指令判 CY 转移指令 JC relJNC rel 第一条指令的功能是如果 CY 等于 1 就转移,如果不等于 1 就顺序执行。那么转移到什么地方去呢?我们可以这样理解:JC 标号,如果等于 1 就转到标号处执行。这条指令我们在上节课中已讲到,不再重复。第二条指令则和第一条指令相反,即如果 CY=0 就转移,不等于 0 就顺序执行,当然,我们也同样理解: JNC 标号判位变量转移指令 JB bit,relJNB bit,rel 第一条指令是如果指定的 bit 位中的值是 1,则转移,否则顺序执行。
同样,我们可以这样理解这条指令:JB bit,标号第二条指令请大家先自行分析下面我们举个例子说明:ORG 0000HLJMP STARTORG 30HSTART:MOV SP,#5FHMOV P1,#0FFHMOV P3,#0FFHL1: JNB P3.2,L2 ;P3.2 上接有一只按键,它按下时,P3.2=0JNB P3.3,L3 ;P3.3 上接有一只按键,它按下时,P3.3=0LJM P L1L2: MOV P1,#00HLJMP L1L3: MOV P1,#0FFHLJMP L1END 把上面的例子写入片子,看看有什么现象………..按下接在 P3.2 上的按键,P1 口的灯全亮了,松开或再按,灯并不熄灭,然后按下接在 P3.3 上的按键,灯就全灭了。
这像什么?这不就是工业现场经常用到的“启动”、“停止”的功能吗?怎么做到的呢?一开始,将 0FFH 送入 P3 口,这样,P3 的所有引线都处于高电平,然后执行 L1,如果 P3.2 是高电平(键没有按下),则顺序执行 JNB P3.3,L3 语句,同样,如果 P3.3 是高电平(键没有按下),则顺序执行 LJMP L1 语句。这样就不停地检测 P3.2、P3.3,如果有一次 P3.2 上的按键按下去了,则转移到 L2,执行 MOV P1,#00H,使灯全亮,然后又转去 L1,再次循环,直到检测到 P3.3 为 0,则转 L3,执行 MOV P1,#0FFH,例灯全灭,再转去 L1,如此循环不已。大家能否稍加改动,将本程序用 JB 指令改写