为什么在嵌入式处理器中,我首先需要设置 GPIO 的值,然后再设置方向?

电器工程 嵌入式 GPIO
2022-01-09 09:50:44

我有一份固件工程师的全职工作。我最近接到了一项任务来检查 GPIO 配置并根据需要更改设置。我发现了一些配置错误的引脚,所以我很自然地重新配置了它们,但是我被告知我以错误的顺序进行了配置。这就是我所说的:

之前:
GPIO1.direction = INPUT;

之后:
GPIO1.direction = OUTPUT;
GPIO1.value = 0;

然而,在代码审查期间,我被告知我需要将初始化顺序更改为以下内容:

GPIO1.value = 0;
GPIO1.direction = 输出;

换句话说,先设置值,然后设置引脚的方向。我还被告知这就是现代处理器需要的方式,因为它们使用两个寄存器,一个用于输入,一个用于输出,但是旧处理器只使用一个寄存器,因此操作顺序无关紧要。
(注:现代 = ARM Cortex M3 及以上,旧 = Intel 8051)

我在工作中要求更好的解释,但我无法得到一个好的答案。这就是为什么我决定在这里问。

所以这是我的问题:

  1. 为什么初始化顺序在新处理器上很重要?
  2. 为什么初始化顺序在旧处理器上无关紧要?
  3. 他们在现代处理器中谈论的是哪两个寄存器?
  4. 他们在旧处理器上谈论什么单个寄存器?

如果有人可以提供某种图表,那就更好了。

3个回答

最初的 8051 使用所谓的伪双向输出端口(带上拉的漏极开路),因此实际上没有端口方向设置。

当然,对于现代真正的双向输出端口,最好在启用端口引脚进行输出之前设置一个已知值,否则您可能会在输出上产生一个瞬态,这可能会导致一些不受欢迎的事情。

例如,请在此处查看我的答案

编辑:这是(相对)现代 CMOS微控制器的 I/O 引脚结构:

在此处输入图像描述

TRIS(TRIState)在许多其他微控制器中称为 DDR(数据方向寄存器)。在这种情况下,如果 TRIS 锁存器输出为高电平,则两个晶体管都“关闭”,但仍可以读取端口。

这是较新的 Microchip micro的稍微复杂的 I/O 引脚结构

在此处输入图像描述

同样,TRIS 锁存器禁用输出。这个包括一个 LAT 锁存器,有助于避免读取-修改-写入问题在 PIC 系列上,您应该只写入 LAT 寄存器(并从 PORT 寄存器读取)。

这是原始的 8051 和 CMOS 8051 经典 I/O 端口引脚内部电路(来自此来源):

在此处输入图像描述

有一点额外的复杂性,因为有一个加速晶体管与上拉并联,它会短暂打开以克服外部电容。如您所见,根本没有 TRIS/DDR 控制。正常操作中使用的上拉 MOSFET 是“弱的”——它们足够小(低 Idss),连接到引脚的外部输出可以将伪双向端口线拉低。

如果您先设置方向,则引脚将被短暂配置为输出其当前输出值。如果您先设置该值,则不会发生这种情况。

因此,按照建议的方式进行操作可以避免输出出现故障,这可能从无害到灾难性,具体取决于引脚连接到什么。

假设默认方向是一个输入(即 High-Z,这是有道理的,因为我们不希望 MCU 强制连接线路上的任何值),这种设置端口的顺序是可取的,但不是必需的。实际上,当您的应用程序要求在启动时端口的值不会是1. 然后您将值设置为0,然后更改方向。在这种情况下,您可以避免设置方向和值之间可能出现的瞬时“故障”,这可能会导致该引脚上出现尖峰。对于所有具有这种逻辑的处理器都是如此,而不仅仅是新处理器。