|
浅谈“读—修改—写”操作 在做“读—修改—写”操作时,单片机首先将欲修改的寄存器的内容读回ALU,对相应位进行修改,然后再整个写回原来的寄存器地址。通常在对寄存器的某一位进行置位、清零、检测、传送或逻辑运算时指令的实际执行过程为“读—修改—写”。熟悉指令的“读—修改—写”实质对于硬件和软件设计都至关重要,尤其在对单片机的I/O口进行上述操作时,忽略这个问题可能会出现意想不到的情况。因为不像内部寄存器,I/O口是与外围电路相连的,“读—修改—写”操作读回的值可能并不是原来写入的值。
下面以51和PIC两种单片机为例阐述二者“读—修改—写”操作的差异以及对硬件设计产生的影响。
PIC单片机的I/O口为完全的双向口,读写方向由端口方向寄存器控制。PIC单片机操作指令读I/O口寄存器时,读的是I/O口引脚上电平的实际状态。当用BSF、BCF、BTFSS、BTFSC四条指令对I/O口进行按位修改或测试之前,单片机首先要将端口寄存器的值读回。设想如下情况:用I/O口第0位驱动晶体管的基极,当输出为1时晶体管导通。然而一旦晶体管导通,I/O口的电平将会被钳位在晶体管BE结导通压降上(0.7伏左右)。若此时想用BSF或BCF给同一个I/O口的其他位进行操作,则会出现“读—修改—写”造成的问题——由于读端口寄存器实际上读的是引脚上的电平,ALU中读回的端口寄存器值第0位实际上为0(而不是原来写的1),这样在修改完毕再写回去时,第0位就真的变成了0,于是原来导通的晶体管将意外关断。解决此问题的方法是在I/O口和基极之间串联一个电阻,用电阻上的压降抬高I/O口电平至TTL阈值以上,这样读回的就是1了。
51单片机有四个I/O口P0~P3,对端口的操作分为读锁存器和读引脚两种方式。由于在其I/O口硬件设计时内部数据总线与端口锁存器输出以及外部引脚分别经过缓冲电路直接关联,通过读锁存器和读引脚的方法可以分别读取端口寄存器的写入值或者I/O口引脚上的实际电平状态。在使用ANL、ORL、XRL、CLR、SETB等位操作指令对I/O口进行按位修改时,单片机将首先读回端口锁存器的值,送入ALU进行相应位修改,再写回端口寄存器,通过驱动电路输出给外围电路。注意这里不会出现像PIC单片机的问题:读回来的是端口锁存器的值而不是I/O口引脚的状态,所以即使驱动晶体管的基极使得引脚电平被钳位为低,ALU中读回的依然是1,这样在返写时不会使晶体管意外关断。
|