Ground Embedded KO Subscribe

Notes / MCU Firmware

GPIO: every setting on a single pin

Input and output, push-pull and open-drain, pull-ups, speed and alternate functions. What each STM32 GPIO register corresponds to in the circuit.

GROUND EMBEDDED · NOTEMCU Firmware 03GPIOAvg 30%D1 period
MODERin · out · AF · analogOTYPERpush-pull · open-drainOSPEEDRoutput speedPUPDRpull-up · pull-downPin
The settings on one pin. Which register decides what, in order.

Configuration registers (STM32F4)

Register Setting
MODER Input / output / alternate function (AF) / analog
OTYPER Push-pull / open-drain
OSPEEDR Output edge speed
PUPDR Pull-up / pull-down / none
IDR Read the input value
ODR Output value
BSRR Set / clear bits atomically
AFR Alternate function number (UART, SPI, timer …)

How to choose the settings

  • Button input: input + internal pull-up, button to ground
  • LED, MOSFET gate: push-pull output
  • I2C: alternate function + open-drain (+ external pull-ups)
  • ADC input: analog mode (disconnects the digital input stage, reducing leakage and noise)
  • Unused pins: analog mode or output LOW

Output speed

Raising OSPEEDR sharpens the edges, which helps fast communication but increases noise and ringing. For LEDs and relays, leave it at the lowest setting.

Atomic writes

BR15 ~ BR01 drives that pin LOWBS15 ~ BS01 drives that pin HIGH
The BSRR register. Writing 1 to the lower 16 bits sets a pin and writing 1 to the upper 16 bits clears it. Bits written as 0 are unchanged.

ODR |= x is a read-modify-write, so it can race with an interrupt. Writing to BSRR changes only the chosen bits in a single write, which is safe.

The settings on one pin

Setting Choices When
Mode Input, output, alternate function, analog The pin's role
Output type Push-pull, open-drain Open-drain when several devices share one line
Pull-up / pull-down None, pull-up, pull-down Inputs that could float
Speed Low to very high Only as much as needed. Faster means more noise

Turning on an LED with registers (STM32 example)

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;        // 1) turn on the port clock first

GPIOA->MODER &= ~(0x3u << (5 * 2));         // 2) clear the PA5 mode field
GPIOA->MODER |=  (0x1u << (5 * 2));         //    01 = output

GPIOA->BSRR = (1u << 5);                    // 3) on  (set)
GPIOA->BSRR = (1u << (5 + 16));             //    off (reset)

The most common mistake is leaving out step 1. A peripheral whose clock is off ignores writes to its registers. If the code looks fine but the pin does not move at all, check the clock first.

The reason to use BSRR instead of ODR |= ... is that there is no read-modify-write sequence, so an interrupt touching another pin on the same port cannot overwrite your change, or you its.

RoadmapSee where this note sits in MCU Firmware→

Push-pull and open-drain

  • Push-pull: drives both HIGH and LOW directly. Used for most outputs, such as LEDs and chip-select signals.
  • Open-drain: only pulls LOW and leaves HIGH to an external pull-up. Used for buses where several devices share a line, such as I2C, and for connections between different voltages.

If you tie two push-pull outputs to one line and one drives HIGH while the other drives LOW, a large current flows from supply to ground and damages the pins.

Inputs must not float

An input pin with nothing connected wanders between 0 and 1 with the surrounding noise. For an input that is connected in only one state, such as a button, turn on the internal pull-up or pull-down. Leaving unused pins in analog mode or as output LOW reduces current consumption.

Reading a button with debounce

bool button_pressed(void) {
    static uint8_t hist = 0xFF;
    hist = (uint8_t)((hist << 1) | ((GPIOC->IDR >> 13) & 1u));   // call every 1 ms
    return hist == 0x00;                                           // LOW 8 times in a row
}

The value read every 1 ms is shifted into 8 bits, and it only counts when the same value was seen 8 times in a row. The few milliseconds of contact bounce are filtered out naturally.

Pin current limits

There is a limit on the current one pin can supply, and separate limits on the total for a port and for the whole chip. When driving several LEDs directly, check the total. Loads such as relays and motors must always go through a transistor.

FREE PDFGet the 3 free ebooksIf you want to keep reading this topic as one book: BLDC motor control, serial communication and sensors at book length. PDFs are in Korean.Get them free →