51 单片机有四个 8 位的并行接口。由于内部结构的特点,并行接口在输出 0、1 的时候,能力是不一样的。输出 0 的时候,能力较强,但输出 1 的时候,能力就很差了,而 P0 口,则要外接上拉电阻才能输1。
单片机从端口读入数据的通道有两个,一个是从锁存器引入,一个是从输出引脚处引入,分别叫做“读锁存器”和“读引脚”。单片机在进行端口输出时,经常要参考其上一次的输出状态。
Example:使一个LED灯闪烁。编程序时需要从输出引脚读前一次的输出状态,然后将其求反输出。如果上次是输出“1”使LED点亮,这时候虽然端口上输出逻辑是“1”,但是由于LED的二极管作用将输出高电平拉至“0”电平(0.7V左右),通过引脚读进来就是“0”而非“1”了。这样,将“0”求反后输出还是“1”,就起不到使灯闪烁的目的了。但是,如果这时读的不是端口而是锁存器的输出端Q,则实现闪烁的功能就正常。上述例子很好地说明了为什么单片机在设置读端口功能后还要设置读锁存器这一功能。
而对于LED的二极管作用将输出高电平拉至“0”电平,实际上外接电路,很容易把引脚的电平拉低,这也就是为什么二极管能将输出高电平拉至“0”电平。
读引脚由传送指令MOV实现
读锁存器用到的“读-改-写”指令用 ANL P0,A等实现
部分内容转载:https://blog.csdn.net/baidu_33836580/article/details/50579098
https://blog.csdn.net/AndyNikolas/article/details/72594215
浅谈“读—修改—写”操作
在做“读—修改—写”操作时,单片机首先将欲修改的寄存器的内容读回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,这样在返写时不会使晶体管意外关断。