推挽/开漏;上拉/下拉

电器工程 微控制器 GPIO
2022-01-15 00:13:50

我正在阅读 ARM Cortex 芯片的数据表,特别是 GPIO 章节。最终,我想配置各种 GPIO 引脚以在“备用功能”模式下使用它们来对 SRAM 进行读/写访问。

在所有可用的 GPIO 寄存器中,我不明白两个:GPIO_PUPDR分别GPIO_OTYPE是“上拉/下拉寄存器”和“输出类型寄存器”。

因为GPIO_PUPDR我有三个选择:

  • 没有上拉或下拉
  • 拉起
  • 拉下

因为GPIO_0TYPE我有两个选择:

  • 输出推挽
  • 输出开漏

所有不同配置之间有什么区别,哪种配置最适合 SRAM 通信?

我正在处理的电路板的文档可在此处获得(参见第 24 页的 SRAM 原理图)。此处提供了 ARM 芯片的参考手册(有关 GPIO 寄存器,请参见第 145 和 146 页)。

3个回答

这个答案对处理器和外围设备是通用的,最后有一个特定于 SRAM 的注释,这可能与您的特定 RAM 和 CPU 有关。

输出引脚可以三种不同的模式驱动:

  • 漏极开路- 晶体管连接到低电平,仅此而已
  • 开漏,带上拉- 晶体管连接到低电平,电阻器连接到高电平
  • 推挽- 一个晶体管连接到高电平,一个晶体管连接到低电平(一次只有一个操作)

输入引脚可以是门输入,具有:

  • 上拉- 一个电阻连接到高
  • 下拉- 一个电阻连接到低
  • 上拉和下拉 - 一个连接到高电平的电阻器和一个连接到低电平的电阻器(仅在极少数情况下有用)。

还有一种施密特触发输入模式,其中输入引脚通过弱上拉拉至初始状态。当它被单独放置时,它会保持其状态,但可能会以最小的努力被拉到一个新的状态。

当多个栅极或引脚通过(外部或内部)上拉连接在一起时,开漏非常有用。如果所有引脚都为高电平,则它们都是开路并且上拉将引脚驱动为高电平。如果任何引脚为低电平,则它们在绑在一起时都会变低。这种配置有效地形成了一个AND门。

_____________________________

2019 年 11 月添加的注释 - 7 年多后:组合多个集电极/漏极开路输出的配置传统上被称为“有线 OR”配置。将其称为 OR(甚至传统上)并不能使它成为一个。如果您使用负逻辑(传统上可能是这种情况),情况会有所不同,但在下文中,我将坚持正逻辑约定,除非特别说明,否则这是正确使用的。

多年来,关于形成“与”门的上述评论已被多次询问 - 并且有人建议结果是“真的”是一个“或”门。这很复杂。

简单的图片是,如果几个集电极开路输出连接在一起,那么如果任何一个集电极开路晶体管导通,那么公共输出将为低电平。为了使公共输出为高,所有输出都必须关闭。

如果您考虑组合 3 个输出 - 要使结果变高,所有 3 个输出都需要单独变高。111 -> 1. 那是一个“与”。

如果您将每个输出级视为一个反相器,那么对于每个具有高输出的输出级,它的输入必须是低的。因此,要获得组合的高输出,您需要三个 000 -> 1 。那是一个“NOR”。

有人建议这是一个 OR - 任何具有至少 1 个的 XYZ 都是 1 -> 1。
我不能真正将这个想法“强加”到这种情况上。

_________________________________

在驱动 SRAM 时,您可能希望尽可能稳定且快速地将数据线或地址线驱动为高或低,以便需要主动向上和向下驱动,因此表示推挽。在某些具有多个 RAM 的情况下,您可能想要做一些巧妙的事情并合并行,而另一种模式可能更适合。

使用带有来自 SRAM 的数据输入的 SRAM,如果 RAM IC 始终断言数据,那么没有上拉的引脚可能是可以的,因为 RAM 始终设置电平,这可以最大限度地减少负载。如果 RAM 数据线有时是开路或三态,您将需要输入引脚能够设置自己的有效状态。在非常高速的通信中,您可能希望使用上拉和下拉,因此并联的有效电阻是终端电阻,总线空闲电压由两个电阻设置,但这有点专业。

我从STM32 Understanding GPIO Settings中找到了这个答案

  • GPIO_PuPd(上拉/下拉)

在数字电路中,绝不允许信号线“浮动”,这一点很重要。也就是说,它们需要始终处于高状态或低状态。浮动时,状态是不确定的,会导致一些不同类型的问题。

纠正这个问题的方法是在信号线上添加一个电阻到 Vcc 或 Gnd。这样,如果线路没有被主动驱动为高电平或低电平,电阻器将导致电位漂移到已知水平。

ARM(和其他微控制器)具有执行此操作的内置电路。这样,您无需在电路中添加另一部分。比如选择“GPIO_PuPd_UP”,相当于在信号线和Vcc之间加了一个电阻。

  • GPIO_OType(输出类型):

Push-Pull:这是大多数人认为“标准”的输出类型。当输出变低时,它被主动“拉”到地。相反,当输出设置为高电平时,它会被主动“推”向 Vcc。简化后,它看起来像这样: 在此处输入图像描述

另一方面,开漏输出仅在一个方向上有效。它可以将引脚拉向地面,但不能将其拉高。想象一下前面的图像,但没有上 MOSFET。当它不拉到地时,(下侧)MOSFET 只是不导电,这会导致输出浮动。

对于这种类型的输出,需要在电路中添加一个上拉电阻,这会导致线路在未被驱动为低电平时变为高电平。您可以使用外部部件或通过将 GPIO_PuPd 值设置为 GPIO_PuPd_UP 来执行此操作。

这个名字来源于 MOSFET 的漏极在内部没有连接到任何东西。当使用 BJT 而不是 MOSFET 时,这种类型的输出也称为“集电极开路”。

  • GPIO_速度

基本上,这控制了输出信号的转换速率(上升时间和下降时间)。压摆率越快,电路辐射的噪声就越多。保持压摆率缓慢是一种很好的做法,并且只有在您有特定原因时才增加它。

还有一点小花絮:对于没有明确“漏极开路”模式的微控制器,例如 AVR 和基于 Arduino ATmega328 的板,例如 Uno,可以通过编写包装函数来模拟这种“漏极开路”模式当您发送它时,它只是将一个引脚设置为“输出低电平”,当您发送它时,它会将0引脚配置为“输入低电平”(高阻抗模式,内部上拉电阻未打开)1通过这种方式,您可以获得相同的效果。这些现代 32 位 ARM 内核微控制器只是有更多选择而已。

此外,与上述链接的 STM32 参考手册的 p146指出以下[我的补充在方括号中]

– 开漏模式:输出寄存器中的“0”激活 N-MOS [从而通过将引脚连接到 GND 来主动驱动低电平],而输出寄存器中的“1”使端口处于 Hi-Z(P- MOS 永远不会被激活)[高阻抗模式——与没有上拉或下拉电阻的浮动输入相同]

– 推挽模式:输出寄存器中的“0”激活 N-MOS [通过将引脚连接到 GND 主动驱动低电平],而输出寄存器中的“1”激活 P-MOS [通过连接主动驱动高电平引脚到 VCC]


在 Arduino 代码中,“包装函数”可以这样实现:

digitalWriteOpenDrain(byte pin, bool state)
{
    // Actively drive LOW
    if (state==LOW)
    {
        pinMode(pin, OUTPUT);
        digitalWrite(pin, LOW);
    }
    // High impedance mode 
    // (note that an internal or external pull-up resistor can optionally be added if you like, according to your requirements)
    else //state==HIGH
    {
        pinMode(pin, INPUT);
        digitalWrite(pin, LOW);
    }
}

或简化:

digitalWriteOpenDrain(byte pin, bool state)
{
    digitalWrite(pin, LOW);

    // Actively drive LOW
    if (state==LOW)
    {
        pinMode(pin, OUTPUT);
    }
    // High impedance mode
    // (note that an internal or external pull-up resistor can optionally be added if you like, according to your requirements)
    else //state==HIGH
    {
        pinMode(pin, INPUT);
    }
}

请注意,要打开 Arduino 上的内部上拉电阻,您可以执行以下操作:

pinMode(pin, INPUT_PULLUP);

或者(同样的事情):

pinMode(pin, INPUT);
digitalWrite(pin, HIGH);

补充阅读: