GPIO (aka General Purpose input/output) is the simplest of microcontroller IO. Even so, GPIO comes in various types and varieties. There is input, output, pull-up, pull-down, push-pull, high-drive, open-drain and more. We will take a look at each of these and cut through the confusion so you know exactly how you need to configure your pins.
GPIO input modes include
- high impedance,
- hysteresis (not usually optional, but we will talk about it anyway)
Floating, High Impedance, Tri-Stated
Floating, high impedance and tri-stated are three terms that mean the same thing: the pin is just flopping in the breeze. Its state is indeterminate unless it is driven high or low externally. You only want to congfigure a pin as floating if you know it will be driven externally. Otherwise, configure the input using pulling resistors.
A Word on Impedance. Impedance is very similar to resistance but considers how a circuit reacts when a changing voltage is applied. A resistor only has resistance. But inductors and capacitors have impedance (resistance + reactance). Now you know!
If an input is configured with an internal pull-up, it will be high unless it is externally driven low. Pull-down inputs do the opposite ( they’re low unless driven high). Some GPIO pins also support changing the pull-up and pull-down settings dynamically using repeater mode (but truth be told, I have never configured a pin that way but we will take a look anyway).
When a GPIO is configured in repeater mode, the pull-up is enabled when the pin is driven high, and the pull-down is enabled when the pin is driven low. If nothing is driving the pin, the pin will retain its last known state (so I guess “repeater” isn’t just a clever name). In some cases, this can prevent a pin from floating which is good.
You might be wondering why pins shouldn’t be floating. When pins are floating, current can leak in and out of the pin. \( leaky+current = bad \). So, don’t leave pins floating.
Virtually all GPIO inputs use a principle called hysteresis to prevent spurious changes in state when an input value changes. I think of hysteresis of having a low threshold to go low and a high threshold to go high. So if you are somewhere in the middle, nothing changes. You can see this in the graph below on where
A (with no hysteresis) has some state changes on that
B (with hysteresis) filters out.
The low threshold can be found in the datasheet in the “Electrical Characteristics” section as VIL and the high threshold is VIH.
A push-pull output is another aptly-name GPIO mode. The pin as the ability to “push” the signal high or “pull” it low. It does this using a pair of complementary transistors. You have probably heard of “CMOS” technology. The C stands for “complementary”. A CMOS device has a pushing transistor (PMOS) and a pulling transistor (NMOS).
In the circuit below where
I is the input and
O is the output
PMOSis off and
NMOSis on which makes
PMOSis on and
NMOSis off which makes
To understand what open drain means, we need to look at the anatomy of a MOSFET transistor. The MOSFET (NMOS in this case) has three terminals.
- Drain (spoiler-alert this is the “drain” part of “open-drain”)
On an open-drain pin, there is no “push” transistor. So
Ois pulled to 0
Ois “open” (get it? The drain is open as in open-drain pin)
If you recall about 2 minutes ago, we don’t want to leave pins floating so in most cases open-drain pins will have an external pullup resistor. If you are really tricky (of course, you are), you can configure the MCU’s pull-up resistor and use the pin in open-drain output mode.
One of the cool things about open-drain pins is that you can have more than one open drain output connected to an MCU input. If any of the open-drains are pulling the line to zero, the input will be zero. Since none are ever pushing, you won’t have any digital infighting (which is worse than floating pins). This is why many sensors have open-drain outputs for signaling events. You can connect a bunch of them to one microcontroller interrupt then use the I2C (or other bus) to see which one is active.
When a GPIO has high drive capability, it is just a push-pull pin that can source or sink more current than usual. A typical push-pull output is able to source/sink around +/-8ma where a high drive output may be up to +/-40ma. Again, that “Electrical Characteristics” section of the datasheet is your goto source for the details.
Understanding the current capabilities of pins is important if you are trying to drive LEDs or do anything that is more than just sending data back and forth. If you want a nice bright LED indicator, you will use about 20ma which is more than a run-of-the-mill GPIO pin can provide.
For a brief re-cap, GPIO is the simplest IO on microcontrollers. However, it turns out it isn’t that simple. You will want to be deliberate about setting input pins with (or without) pulling resistors. For outputs, remember push-pull vs open-drain and make sure you have enough drive current for the task at hand.
Readability changes published on September 11 (never forget), 2019