前两天看材料,见到关于I/O口作为输入时,要先输出1的阐明,有点利诱。今日特意查了一些材料,费了半响劲,尽管还没有彻底弄理解,但也算有所收成,下面就列出来,以便将来查询并进一步弥补。
1、作为I/O口运用时,输入和输出原理
作I/O口运用时,在操控信号的效果下,与门封闭,V1截止,一起多路开关打向下边,与锁存器的反向输出端Q^相连。
输出数据时,“写锁存器”端宣布脉冲,将“内部总线”上的数据写入输出锁存器,由Q^端操控V2,从而在引脚上反应出相应的状况。此种运用时P0端口各引脚应外接上拉电阻。
输入数据时,分为读引脚和读端口两种方法。读端口的方位便是上图中的“读锁存器”,而读引脚则是上图中的“读引脚”。至于何时读端口,何时读引脚则是依据不同的指令由硬件自动完结的,这不需求咱们操心。
附:
读端口的指令
读端口的指令为端口内容取反这样的“读-修正-写”指令。材料称:下面这些的指令才有Read-Modify-Write成效
ANL (logical AND, e.G., ANL P1,A)
ORL (logical OR, e.g., ORL P2,A)
XRL (logical EX-OR, e.g., XRL P3,A)
JBC (jump if bit = 1 and clear bit, e.g., JBC P1.1, LABEL)
CPL (complement bit, e.g., CPL P3.0)
INC (increment, e.g., INC P2)
DEC (decrement, e.g., DEC P2)
DJNZ (decrement and jump if not zero, e.g., DJNZ P3, LABEL)
MOV PX.Y,C(move carry bit to bit Y ofPORTX)
CLR PX.Y(clear bit Y ofPORTX)
SETB PX.Y(set bit Y ofPORTX)
读引脚的指令
如下所示,读之前应先将端口置1,即先输出1,修正锁存器的内容为1。
MOV A, P1
MOV 20H, P1
MOV R0, P1
MOV @R0, P1
2、为什么读之前要先写1?
从上图可知,假如不对端口置1,端口锁存器本来的状况有或许为0,Q端为0,Q^为1,加到场效应管栅极的信号为1,该场效应管就导通对地出现低阻抗,此刻即便引脚上输入的信号为1也会因端口的低阻抗而使信号拉低,使得外加的1信号读入后纷歧定是1,若先履行置1操作则能够使场效应管截止,引脚信号直接加到三态缓冲器中,完成正确的读入。
3、实践运用
P0、P1、P2、P3作I/0口运用时,假如要从外部读取数据,读取之前应先将端口置1。因初始化时,四个I/O均被初始化为0xFF,所以若端口在整个程序过程中无输出时,即输出锁存器的状况一直为1,则读数据时可不必手动置1。(附:参阅引脚内部结构图可知,纵使锁存器D口数据在变(内部数据线),只需时钟触发端clk没有触发信号,锁存器中的内容永久都不会改动,也便是说,不论外部引脚信号怎么变,也不论履行过多少次读引脚操作,端口锁存器中的内容是不会发生改变的。那么,端口内容何时改变?答曰:只需履行过一次输出,端口内容必为输出值,由于端口便是输出的数据锁存器。)
而当端口实践运用时要不停地同外部数据交换时,即又有输出又有读入时,如单片机与存储器24C16经过I%&&&&&%总线相连,SCL总是由单片机输出可不必考虑,而SDA则可经过单片机向外发数据,又能够从外部读数据,假若之前发送的最终一位数据为0时,此刻若再读数据,由于锁存器的状况仍为0,则之后当即读数据时就有或许犯错。所以实践操作时,在发送数据代码之后,总会有一个单片机自动将SDA拉高的指令,之后再读数据时才不会出问题。(自己浅见,纷歧定正确)
而当P0与P2口作总线运用与外部并口衔接时,应该就不会有上面的问题,由于从上图可知,当作总线运用时,在操控信号的效果下,与门导通,一起多路开关经过反向器与“地址/数据总线”衔接,此刻V1与V2的驱动电路构成反相,构成推拉式电路。在这种情况下输出时,可直接驱动电路,不需求接上拉电阻(由于V1导通)。而输入时,直接读引脚即可,不需置1。(由于输入时,地址/数据线上没有数据,V2应该截止(我以为的,此处存疑)。
P1_0=!P1_0在KEIL中编译后的反汇编指令为CPL 1.0;从上面所述可知为读端口指令(读-修正-写),所以能够在C中直接运用,如用作看门狗的铲除脉冲和LED灯的闪耀等。
读端口指令似乎是要对内部的端口寄存器(P0~P4)进行改写时才进行的,所以说要先读端口锁存器状况,改写完后一起有锁存器输出。而读引脚指令没有改写寄存器。