Updated: 24 April 2019
Anyone who writes software for microcontrollers will have to configure and manage general purpose input/output (GPIO) pins. On their surface, GPIO configuration seems simple: pins are input or output, and they can be high or low.
However, inevitably you will come across a fancy processor with a plethora of configuration options, or an electrical engineer will request pin settings which you don't understand ("make this line Hi-Z").
This guide aims to help you understand different pin configuration options that are provided on modern microcontrollers.
Table of Contents:
- Background Information
- Tri-state Logic
- Current Sink
- Current Source
- Input and Output Modes
- GPIO Input Modes
- GPIO Output Modes
- Push-Pull Output
- Open-Drain Output
- High Drive
- Further Reading
- Change Log
Before we dive into configuration options, it's useful to understand some general descriptions and terms that are associated with GPIO and IO signals.
Most modern GPIO lines are implemented as a tri-state buffer. This means that the GPIO line can effectively assume three values:
- Logical 0 (connection to ground)
- Logical 1 (connection to VCC)
- High-impedance (also called "floating", "Hi-Z", "tri-stated")
When a line is put into a high-impedance state, the output is effectively removed from the circuit. This allows multiple circuits or devices to share the same output lines and is commonly utilized to implement communication busses. Failure to utilize a high-impedance state when it's required leads to IO contention and short-circuits.
A signal is said to be "floating" when its state is indeterminate, meaning that it is neither connected to VCC or to ground. The signal's voltage will "float" to match the residual voltage.
The term "floating" is often used interchangeably to describe a pin which is in the high-impedance state.
Pull-ups are resistors that connect an signal to VCC. Pull-ups are used to set a default state when the signal is floating.
Recall that when an input pin is in high-impedance mode and not driven by external sources, it is floating at a residual voltage level. Pull-up resistors prevent the pin from floating by forcing the signal to VCC when it is not being actively driven. When another source drives the signal low (connects to ground), the pull-up is overridden and the input pin will read a '0'.
Many microcontrollers supply internal pull-up configuration options. Sometimes, a specific pull-up resistor value is required which necessitates using an external pull-up instead of a chip's internal pull-up.
Pull-downs are resistors that connect an signal to ground. Pull-downs are used to set a default state when the signal is floating. When another source drives the signal high (connects to VCC), the pull-down is overridden and the input pin will read a '1'.
Many microcontrollers supply internal pull-down configuration options. Sometimes, a specific pull-down resistor value is required which necessitates using an external pull-down instead of a chip's internal pull-down.
A "current sink" means that current is flowing into a pin, node, or signal. For digital IO, a current sink provides the ground connection to the load.
A "current source" is the opposite of a current sink: the current is flowing out of a pin, node or signal. For digital IO, a current source provides the voltage source to the load.
Both a current source and a current sink have current flowing, but in different directions.
Input and Output Modes
The primary configuration option for a GPIO pin is input or output.
GPIO Input Modes
When a GPIO is configured as an input, it can be used to read the state of the electrical signal. Configuring a GPIO as an input puts the pin into a high-impedance state.
In general, there GPIO inputs are primarily configured in one of three ways:
- High-impedance (default - floats if not driven)
- Pull-up (internal resistor connected to VCC)
- Pull-down (internal resistor connected to Ground)
Most GPIO input pins also feature internal hysteresis, which prevents spurious state changes on the pins. Usually hysteresis is a built-in feature, rather than a configurable setting.
GPIO Output Modes
When a GPIO is configured as an output, it can be used to drive a signal high or low. There are primarily two configuration options for GPIO outputs: push-pull and open-drain.
Push-pull is the default GPIO output setting in most cases. A push-pull GPIO has the ability to both source and sink current.
With a push-pull GPIO, a transistor connects to VCC or GND to drive a signal high or low. When the output goes low, the signal is actively "pulled" to ground, and when the output goes high it is actively "pushed" to VCC.
Unlike push-pull, an open-drain output can only sink current. The output has two states: low and high-impedance. In order to achieve a logical high output on the line, a pull-up resistor is used to connect the open-drain output to the desired output voltage level.
You can think of an open-drain GPIO as behaving like a switch which is either connected to ground or disconnected.
Open-drain GPIO can typically be configured in two different modes:
- Open-drain with internal pull-up
Most applications which utilize open-drain circuitry utilize external pull-ups on open-drain outputs. Often, internal pull-up values are not sufficient for the target circuitry.
Open-drain outputs are useful when multiple gates or pins are connected together, such as with the I2C bus. When a device is not using the bus, the open-drain output is in high-impedance mode and the voltage level is pulled high by the pull-up resistor. When a device drives the output low, all connected lines will go low, as they are tied together.
Another common use for open-drain outputs is having multiple external devices drive a single, active-low interrupt pin on a microcontroller.
An "open collector" is functionally the same as an "open drain". An "open collector" refers to a current sink on a BJT transistor output, while an "open drain" refers to a current sink on a FET output.
I encounter "open collector" more on component datasheets than I do on microcontroller datasheets.
GPIO speed controls the slew rate, or the rate at which a signal can change between low/high values (the "rise time" and "fall time"). Speed configuration options are described as "speed", "slew rate", "frequency", and "high-frequency mode".
By increasing the GPIO speed, you increase the rate of change of the output voltage (reducing rise time). However, power consumption and noise radiated by the circuit increases along with the GPIO speed. By default, you should keep GPIO speed low unless there is a specific reason for increasing it.
High-drive GPIO are push-pull pins that are capable of providing more current than typical pins. While your must check each chip's datasheet to understand the current capacity of your pins, typical push-pull GPIO can source/sink around ±8mA, while a high-drive pin can source/sink up to ±40mA.
High-drive pins enable your microcontroller to directly drive IO that requires higher-than-normal current, such as an LED. Using high-drive pins can help simplify the electrical design and reduce cost by eliminating the need for external current amplifying circuitry.
- Fixed typo "change change" -> "can change"
- Added Further Reading section to Table of Concents
- Clarified that an open collector is a current sink for a BJT transistor
Thanks to Gabriel Staples for identifying corrections needed by the article.