1 Microcontroller I/O
Levi Pearson edited this page 2022-03-06 10:48:21 +00:00

I/O & Communication Standards

Voltage Levels

While digital logic has two states, the voltage level on microcontroller pins varies continuously. There are important things to know:

  • What is the nominal voltage level of the "high" signal?
  • What is the nominal voltage level of the "low" signal?
  • What is the lowest voltage that is reliably considered "high" by an input pin?
  • What is the highest voltage that is reliably considered "low" by an input pin?
  • What is the lowest voltage that a will be driven "high" by an output pin?
  • What is the highest voltage that will be driven "low" by an output pin?
  • What is the highest voltage that can be tolerated without damage?
  • What is the lowest voltage that can be tolerated without damage?

You can usually consider "high" values to be all around the source voltage of the controller, and "low" values to be near 0. You should never expose a pin on a microcontroller to a higher voltage than the source voltage powering the microcontroller unless you are certain that it is tolerant of higher voltages.

The STM32F103 has a 3.3V source voltage, so its nominal logic "high" level is 3.3V and the "low" level is 0V. Unusually, many (but not all!) of its I/O pins are 5V tolerant. They can act as inputs to a 5V signal without damage, but they cannot drive their outputs to 5V; they can only indicate logic "high" to a 5V device that recognizes 3.3V as a logic "high" level. This is true of 5V TTL logic, but not of 5V CMOS logic. A 5V CMOS logic input needs at least 3.7V to sense a "high" level, while a 5V TTL input only requires 2V to see a "high" level.

This is not very important if you keep all devices at the same nominal logic level, but when you need to interface devices at different levels the details will determine which strategies will be available.

Push/Pull vs. Open Collector

When the input of one device is connected to the output of another, the output device usually either pushes current to drive the voltage level high, or it pulls (or sinks) current to drive the voltage low. In this configuration, only one device can drive the wire; anything else connected to the wire must passively sense the voltage level.

It is possible to allow multiple devices to drive a wire if they instead work in "open collector" mode. An open collector output will never push current to the wire, it only sinks current to drive the wire low. The high state of the wire is passively determined by "pulling up" the wire through a high-value resistor to the voltage source. Any number of devices can pull the wire low simultaneously without damaging one another.

Current Limits/Requirements

Microcontrollers are usually not designed to supply or sink a lot of current to other devices. There is usually both a per-pin limit and a total limit for all pins. Exceeding this limit can damage your microcontroller, so if you want to use a microcontroller to make something happen (drive a motor, turn on a light, etc.) be sure to use appropriate current-limiting resistors and employ some sort of external circuitry to interface with things that require a lot of power.

Plenty of cheap add-on boards are available that have this kind of circuitry in place for driving various kinds of lights, motors, relays, etc. if you don't feel comfortable with the calculations to design it yourself yet.

Single-Ended vs. Differential

A signal is called "single-ended" if the "high" and "low" voltage levels are determined with respect to a common 0V ground level between endpoints. This is how most low-speed signals on a circuit board work, and how most of the communication protocols supported by peripherals on a STM32F103 work.

Many newer and higher-speed communication protocols use a different technique called "differential" signaling; this uses a pair of driven wires rather than a single driven wire to determine a single signal, but it is much more robust against certain kinds of interference. It works by always driving one of the wires to the opposite level of the other, and measuring the output level by determining which of the wires at the receiver has a higher voltage than the other.

Communication standards that use differential signaling that you may be familiar with are USB, DVI/HDMI, Ethernet, and CAN. The STM32F103 supports both USB and CAN, although you don't need to understand all the signal-level details of those protocols to use them!

Synchronous vs. Asynchronous

A communication signal is "synchronous" if there is a shared clock signal that the endpoints use to sample the data signal. A communication signal is "asynchronous" if there is no clock, and timing has to be managed independently by sender and receiver according to a pre-arranged data rate.

The most common asynchronous signal you are likely to use is the UART-based serial signal. UART stands for "Universal Asynchronous Receiver/Transmitter". Both ends have to be configured for the same transmission rate, which is measured in "baud" for historical reasons, but this corresponds to bits per second most of the time. Successful communication over a UART link requires both ends to have their sampling clocks running at close enough to the same rate that a full byte can be received before enough drift occurs that data is sampled at the wrong point by the receiver.

Both common protocols for linking a microcontroller to external peripherals, I2C and SPI, are synchronous. One device provides the clock, and both ensure that the data signal is driven or is sampled correctly relative to the clock signal edges.