推挽/开漏 上拉/下拉


49

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

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

因为GPIO_PUPDR我有三个选择:

  • 无上拉或下拉
  • 拉起
  • 拉下

因为GPIO_0TYPE我有两个选择:

  • 输出推挽
  • 输出漏极开路

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

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


您能提供所使用的SRAM和ARM CPU的数据表的型号/链接吗?
院长

@Dean:好的。我用两个链接更新了我的问题。
Randomblue 2012年

Answers:


54

该答案对处理器和外围设备来说是通用的,并且在结尾处带有SRAM特定注释,这可能与您的特定RAM和CPU有关。

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

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

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

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

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

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

在驱动SRAM时,您可能希望尽可能牢固,快速地驱动数据线或地址线的高电平或低电平,以便需要有源上下驱动器,因此需要推挽式驱动。在具有多个RAM的某些情况下,您可能需要做一些聪明的事情并合并行,而在其他模式下可能更适合。

对于具有来自SRAM的数据输入的SRAM的RAM,如果RAM IC始终在声明数据,则没有上拉的引脚可能就可以了,因为RAM总是设置电平,这可以最大程度地减少负载。如果RAM数据线有时断路或三态,则需要输入引脚能够设置其自己的有效状态。在超高速通信中,您可能希望使用上拉和下拉,因此并联有效电阻是终端电阻,总线空闲电压由两个电阻器设置,但这有点专业。


只是要清楚一点,“晶体管连接到低电平而没有其他任何东西”是什么意思?晶体管具有3个引脚。每个引脚如何连接?
Randomblue'3

@Randomblue-对不起-晶体管集电极或漏极在充当输出时
Russell McMahon

为了澄清您对“下拉”的回答,“地面”,“低”和“ -ve”之间有什么区别?
Randomblue

我已经对您的问题进行了很多编辑,请您检查一下我是否未犯任何错误?
Randomblue

@Randomblue-编辑似乎很好。这让我想知道我最初写的是什么?您似乎已经说了我的想法:-)。
罗素·麦克马洪

17

我从STM32了解GPIO设置中找到了这个答案

  • GPIO_PuPd(上拉/下拉)

在数字电路中,重要的是切勿让信号线“浮动”。也就是说,它们必须始终处于高状态或低状态。浮动时,状态不确定,并且会导致几种不同类型的问题。

纠正此问题的方法是在信号线与Vcc或Gnd之间增加一个电阻。这样,如果未将线路主动驱动为高电平或低电平,则电阻器将导致电势漂移到已知水平。

ARM(和其他微控制器)具有内置电路来执行此操作。这样,您无需在电路中添加其他零件。例如,如果选择“ GPIO_PuPd_UP”,则等同于在信号线和Vcc之间添加一个电阻。

  • GPIO_OType(输出类型):

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

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

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

该名称源于MOSFET的漏极内部未连接任何东西的事实。当使用BJT代替MOSFET时,这种类型的输出也称为“集电极开路”。

  • GPIO_速度

基本上,这控制了输出信号的转换速率(上升时间和下降时间)。压摆率越快,电路发出的噪声就越大。最好保持缓慢的摆率,只有在有特殊原因时才增加摆率。


3

还有一点建议:对于没有显式“开漏”模式的微控制器,例如AVR和基于Arduino ATmega328的板卡(例如Uno),可以通过编写包装函数来模拟这种“开漏”模式当您将其发送给a时,它只是将一个引脚设置为“ Output LOW”,当您发送给a时,会将0其配置为“ Input LOW”(高阻抗模式,内部上拉电阻未开启)1。这样,您可以获得相同的效果。这些现代的32位ARM内核微控制器仅具有更多选择。

另外,链接到上述内容STM32参考手册的 p146 指出以下内容:[我的补充内容放在方括号中]

–开漏模式:输出寄存器中的“ 0”激活N-MOS [从而通过将引脚连接到GND从而主动将LOW驱动],而输出寄存器中的“ 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);

补充阅读:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.