General Purpose Input/Output (GPIO) pins typically operate with in a logic voltage range of 0 to 3.3V. While certain inputs may tolerate 5V, output stages are strictly limited to the 3.3V supply. To control higher-power devices such as motors or relays, an external driver circuit must be integrated between the MCU pin and the load.
Hardware Architecture
All GPIO peripherals in the STM32 family are connected to the APB2 bus structure. Each GPIO port (e.g., GPIOA) contains 16 distinct I/O lines, indexed from 0 to 15 (e.g., PA0 represents Pin 0 on Port A). Internal registers allow the CPU core to access these pins via the APB2 bus. Since the microcontroller operates as a 32-bit system, the associated registers are 32-bit wide, though only the lower 16 bits correspond directly to individual IO pins. Drivers within the module boost signal current capability for direct switching tasks like LED activation.
Input Configurations
When an input pin is left unconnected, it remains in a floating state susceptible to electrical noise. To ensure defined logic levels, internal pull-up or pull-down resistors should be enabled:
- Pull-Up: Resistor pulls the line high when disconnected.
- Pull-Down: Resistor pulls the line low when disconnected.
These resistors are weak to avoid interfering with active external drivers. For precise analog voltage measurement, the pin can be switched to Analog Mode, bypassing digital buffers to interface directly with the ADC block.
Output Modes
The output stage consists of P-MOS and N-MOS transistor pairs arranged differently based on configuration:
- Push-Pull Output: Both MOS transistors are active. This provides strong drive capabilities for both High and Low states, making it ideal for controlling LEDs, buzzers, and general signals.
- Open-Drain Output: Only the N-MOS transistor is effective. The High state results in a high-impedance state (floating), requiring an external pull-up resistor to achieve a High logic level. The Low state actively drives ground. This is useful for wired-OR logic or driving signals requiring different voltages than the I/O supply.
Setup Procedure
Proper initialization requires a specific sequence to prevent undefined behavior during boot:
- Enable the clock for the specific GPIO port using the RCC peripheral clock controller.
- Initialize the
GPIO_InitTypeDefstructure with desired mode, speed, and pin selections. - Apply the configuration to the hardware.
- Write data values to set output states.
Practical Applications
Single LED Control
This example toggles an LED connected to PA0. The LED activates when the pin is driven Low (common cathode configuration).
#include "stm32f10x.h"
// External delay function declaration
extern void Delay_ms(uint32_t count);
int main(void)
{
// Enable clock for GPIOA
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// Configure PA0
GPIO_InitTypeDef gpio_cfg;
gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP; // Push-Pull
gpio_cfg.GPIO_Pin = GPIO_Pin_0; // Select PA0
gpio_cfg.GPIO_Speed = GPIO_Speed_50MHz; // High-speed transition
GPIO_Init(GPIOA, &gpio_cfg);
while (1)
{
// Turn ON (Low Logic)
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
// Turn OFF (High Logic)
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
}
}
Flowing Lights Sequence
Controls LEDs from PA0 to PA6 sequentially. Active Low logic is assumed.
#include "stm32f10x.h"
extern void Delay_ms(uint32_t count);
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio_cfg;
gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_cfg.GPIO_Pin = GPIO_Pin_All; // Initialize all 16 pins
gpio_cfg.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_cfg);
uint16_t led_mask = 0x0001;
while (1)
{
for (uint8_t i = 0; i < 7; ++i)
{
// Clear current bit to turn on LED (Active Low)
// Set other pins to 1 to turn off
uint16_t port_val = ~(led_mask);
GPIO_Write(GPIOA, port_val);
Delay_ms(300);
led_mask <<= 1; // Move to next pin
}
}
}
Buzzer Actuation
Activates a piezo buzzer connected to PB12. The buzzer sounds when the pin is pulled Low.
#include "stm32f10x.h"
extern void Delay_ms(uint32_t count);
int main(void)
{
// Enable Clock for GPIOB
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef buzzer_cfg;
buzzer_cfg.GPIO_Mode = GPIO_Mode_Out_PP;
buzzer_cfg.GPIO_Pin = GPIO_Pin_12;
buzzer_cfg.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &buzzer_cfg);
while (1)
{
// On
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);
// Off
GPIO_SetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);
}
}