嵌入式系统 - I/O 编程
在 8051 中,I/O 操作使用四个端口和 40 个引脚完成。以下引脚图显示了 40 个引脚的详细信息。I/O 操作端口保留 32 个引脚,每个端口有 8 个引脚。其他 8 个引脚被指定为 Vcc、GND、XTAL1、XTAL2、RST、EA (bar)、ALE/PROG (bar) 和 PSEN (bar)。
它是一个 40 针 PDIP(塑料双列直插式封装)

注意 − 在 DIP 封装中,您可以通过 IC 中间的切口识别第一个引脚和最后一个引脚。第一个引脚位于此切割标记的左侧,最后一个引脚(即本例中的第 40 个引脚)位于切割标记的右侧。
I/O 端口及其功能
四个端口 P0、P1、P2 和 P3,每个端口使用 8 个引脚,使其成为 8 位端口。重置后,所有端口均配置为输入,可用作输入端口。将第一个 0 写入端口后,端口将变为输出。要将其重新配置为输入,必须向端口发送 1。
端口 0(引脚编号 32 - 引脚编号 39)
它有 8 个引脚(32 至 39)。可用于输入或输出。与 P1、P2 和 P3 端口不同,我们通常将 P0 连接到 10K 欧姆上拉电阻,以将其用作开漏输入或输出端口。
它也被指定为 AD0-AD7,允许它同时用作地址和数据。对于 8031(即无 ROM 芯片),当我们需要访问外部 ROM 时,P0 将同时用于地址和数据总线。ALE(引脚编号 31)表示 P0 是否有地址或数据。当 ALE = 0 时,它提供数据 D0-D7,但当 ALE = 1 时,它有地址 A0-A7。如果没有可用的外部存储器连接,则必须在外部将 P0 连接到 10K 欧姆上拉电阻。

MOV A,#0FFH ;(comments: A=FFH(Hexadecimal i.e. A=1111 1111) MOV P0,A ;(Port0 have 1's on every pin so that it works as Input)
端口 1(引脚 1 至 8)
这是一个 8 位端口(引脚 1 至 8),可用作输入或输出。它不需要上拉电阻,因为它们已经在内部连接。重置后,端口 1 配置为输入端口。以下代码可用于将 55H 和 AAH 的交替值发送到端口 1。
;Toggle all bits of continuously MOV A,#55 BACK: MOV P2,A ACALL DELAY CPL A ;complement(invert) reg. A SJMP BACK
如果将端口 1 配置为输出端口,则要再次将其用作输入端口,请通过向其所有位写入 1 来对其进行编程,如以下代码所示。
;Toggle all bits of continuously MOV A ,#0FFH ;A = FF hex MOV P1,A ;Make P1 an input port MOV A,P1 ;get data from P1 MOV R7,A ;save it in Reg R7 ACALL DELAY ;wait MOV A,P1 ;get another data from P1 MOV R6,A ;save it in R6 ACALL DELAY ;wait MOV A,P1 ;get another data from P1 MOV R5,A ;save it in R5
端口 2(引脚 21 至 28)
端口 2 共占用 8 个引脚(引脚 21 至 28),可用于输入和输出操作。与 P1(端口 1)一样,P2 也不需要外部上拉电阻,因为它们已经在内部连接。它必须与 P0 一起使用,为外部存储器提供 16 位地址。因此它也被指定为(A0–A7),如引脚图所示。当 8051 连接到外部存储器时,它为 16 位地址的高 8 位提供路径,并且不能用作 I/O。复位后,端口 2 配置为输入端口。以下代码可用于将 55H 和 AAH 的交替值发送到端口 2。
;Toggle all bits of continuously MOV A,#55 BACK: MOV P2,A ACALL DELAY CPL A ; complement(invert) reg. A SJMP BACK
如果将端口 2 配置为输出端口,则要再次将其用作输入端口,请通过向其所有位写入 1 来对其进行编程,如以下代码所示。
;Get a byte from P2 and send it to P1 MOV A,#0FFH ;A = FF hex MOV P2,A ;make P2 an input port BACK: MOV A,P2 ;get data from P2 MOV P1,A ;send it to Port 1 SJMP BACK ;keep doing that
端口 3(引脚 10 至 17)
它也是 8 位的,可用作输入/输出。此端口提供一些极其重要的信号。P3.0 和 P3.1 分别是 RxD(接收器)和 TxD(发送器),共同用于串行通信。P3.2 和 P3.3 引脚用于外部中断。P3.4 和 P3.5 分别用于定时器 T0 和 T1。P3.6 和 P3.7 是写入 (WR) 和读取 (RD) 引脚。这些是低电平有效引脚,意味着当为它们提供 0 时它们将处于活动状态,并且它们用于在基于 8031 的系统中为外部 ROM 提供读写操作。
P3 位 | 功能 | 引脚 |
---|---|---|
P3.0 | RxD | 10 |
P3.1 < | TxD | 11 |
P3.2 < | Complement of INT0 | 12 |
P3.3 < | INT1 | 13 |
P3.4 < | T0 | 14 |
P3.5 < | T1 | 15 |
P3.6 < | WR | 16 |
P3.7 < | Complement of RD | 17 |
端口 0 和端口 2 的双重角色
端口 0 的双重角色 − 端口 0 也被指定为 AD0–AD7,因为它既可用于数据处理,也可用于地址处理。将 8051 连接到外部存储器时,端口 0 可以同时提供地址和数据。然后,8051 微控制器将输入多路复用为地址或数据,以节省引脚。
端口 2 的双重角色 − 除了用作 I/O 外,端口 P2 还用于与端口 0 一起为外部存储器提供 16 位地址总线。端口 P2 也被指定为 (A8– A15),而端口 0 通过 A0–A7 提供低 8 位。换句话说,我们可以说,当 8051 连接到最大可达 64KB 的外部存储器 (ROM) 时,这可以通过 16 位地址总线实现,因为我们知道 216 = 64KB。端口 2 用于 16 位地址的高 8 位,不能用于 I/O,这是任何外部 ROM 程序代码的寻址方式。
引脚的硬件连接
Vcc − 引脚 40 为芯片提供电源,电压为 +5 V。
Gnd − 引脚 20 为参考提供接地。
XTAL1、XTAL2(引脚编号 18 和引脚编号 19) − 8051 具有片上振荡器,但需要外部时钟来运行它。石英晶体连接在芯片的 XTAL1 和 XTAL2 引脚之间。该晶体还需要两个 30pF 的电容器来产生所需频率的信号。每个电容器的一侧接地。8051 IC 有多种速度,这完全取决于石英晶体,例如,20 MHz 微控制器需要频率不超过 20 MHz 的晶体。

RST(引脚 9) − 它是一个输入引脚和有效高电平引脚。在此引脚上施加高电平脉冲(即 1)后,微控制器将重置并终止所有活动。此过程称为上电复位。激活上电复位将导致寄存器中的所有值丢失。它将程序计数器设置为全 0。为确保复位的有效输入,高电平脉冲必须至少保持高电平两个机器周期,然后才允许其变为低电平,这取决于电容值及其充电速率。 (机器周期是单个指令执行时所需的最小频率量)。
EA 或外部访问(引脚编号 31) − 它是一个输入引脚。此引脚为低电平有效引脚;施加低脉冲后,它会被激活。如果微控制器 (8051/52) 具有片上 ROM,则 EA(bar)引脚连接到 Vcc。但在没有片上 ROM 的 8031 微控制器中,代码存储在外部 ROM 中,然后由微控制器提取。在这种情况下,我们必须将 EA(引脚编号 31)连接到 Gnd,以指示程序代码存储在外部。

PSEN 或程序存储启用(引脚编号 29) − 这也是一个低电平有效引脚,即在施加低脉冲后激活。它是一个输出引脚,与基于 8031(即无 ROM)的系统中 EA 引脚一起使用,以允许将程序代码存储在外部 ROM 中。
ALE 或(地址锁存启用) − 这是一个输出引脚,高电平有效。它特别用于 8031 IC 将其连接到外部存储器。它可以用于决定 P0 引脚是否用作地址总线或数据总线。当 ALE = 1 时,P0 引脚用作数据总线,当 ALE = 0 时,P0 引脚用作地址总线。
I/O 端口和位寻址能力
在为 8051 编写代码时,它是 8051 最广泛使用的功能。有时我们只需要访问端口的 1 或 2 位,而不是整个 8 位。 8051 提供了访问端口各个位的能力。
以单一位方式访问端口时,我们使用语法"SETB X. Y",其中 X 是端口号(0 到 3),Y 是数据位 D0-D7 的位数(0 到 7),其中 D0 是 LSB,D7 是 MSB。例如,"SETB P1.5"设置端口 1 的高位 5。
以下代码显示了如何连续切换位 P1.2。
AGAIN: SETB P1.2 ACALL DELAY CLR P1.2 ACALL DELAY SJMP AGAIN
单比特指令
指令 | 函数 |
---|---|
SETB 位 | 设置位 (bit = 1) |
CLR 位 | 清除位 (bit = 0) |
CPL 位 | 对位求补 (bit = NOT 位) |
JB 位,目标 | 如果位 = 1,则跳转到目标 (如果位,则跳转) |
JNB 位,目标 | 如果位 = 0,则跳转到目标(如果没有位,则跳转) |
JBC 位,目标 | 如果位 = 1,则跳转到目标,清除位(如果位,则跳转,然后清除) |