STM32 Boards

Mastering STM32 Boards

A Complete 5-Day Journey from Basics to Advanced

By Ramu NarlapatiJanuary 29, 202690 min read

Share this article

Welcome to Your STM32 Journey

Welcome to the ultimate STM32 mastery series! Over the next 5 days, we'll transform you from a complete beginner to someone who can confidently build professional STM32 projects. This comprehensive journey covers everything from basic GPIO to advanced features like ADC, DMA, and real-time operating systems.

Why STM32?

  • Industry Standard: Used in automotive, industrial automation, IoT devices, and consumer electronics
  • Powerful ARM Cortex-M Core: 32-bit processing with excellent performance
  • Rich Peripheral Set: Timers, ADC, DAC, communication interfaces (UART, I2C, SPI), and more
  • Excellent Ecosystem: Free development tools, extensive documentation, and active community
  • Scalable: From simple LED control to complex real-time systems

What You'll Learn

Day 1: Foundation & Setup

Architecture, IDE setup, LED blink

Day 2: GPIO & Interrupts

Button input, EXTI, debouncing

Day 3: Timers & PWM

Timer interrupts, PWM, servo control

Day 4: Communication

UART, I2C, SPI protocols

Day 5: Advanced Features

ADC, DAC, DMA, FreeRTOS

Hardware Requirements

  • STM32 Development Board (STM32F103C8T6 "Blue Pill" or STM32 Nucleo)
  • USB to Serial adapter (if using Blue Pill)
  • Breadboard and jumper wires
  • LEDs, resistors (220Ω), push buttons
  • Optional: Servo motor, sensors (DHT11, LM35)

Software Requirements

  • STM32CubeIDE (free, all-in-one development environment)
  • STM32CubeMX (for peripheral configuration)
  • ST-Link drivers
Day 1

Day 1: Foundation & Setup

Today we're building the foundation for everything that follows. We'll understand STM32 architecture, set up your development environment, and write your first program to blink an LED - the "Hello World" of embedded systems.

Understanding STM32 Architecture

ARM Cortex-M Core

STM32 microcontrollers are built around ARM Cortex-M processors (M0, M3, M4, M7). These are 32-bit RISC processors optimized for embedded applications, offering excellent performance per watt.

Memory Organization

  • Flash Memory: Stores your program code (typically 64KB-512KB)
  • SRAM: Volatile memory for variables and stack (typically 20KB-128KB)
  • System Memory: Contains bootloader for programming

Peripherals

STM32 boards come with rich peripherals: GPIO, Timers, ADC, DAC, UART, I2C, SPI, USB, CAN, and more.

Setting Up STM32CubeIDE

  1. Download STM32CubeIDE from ST's website
  2. Install and launch the IDE
  3. Create a new STM32 project
  4. Select your target board (e.g., STM32F103C8)
  5. Configure the project settings

Your First Program: LED Blink

/* USER CODE BEGIN WHILE */
while (1)
{
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);   // LED ON
    HAL_Delay(1000);                                        // Wait 1 second
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); // LED OFF
    HAL_Delay(1000);                                        // Wait 1 second
    /* USER CODE END WHILE */
}

Key Concepts Learned

  • STM32 architecture and memory organization
  • Setting up development environment
  • GPIO configuration and control
  • HAL library basics
  • Compiling and uploading code
Day 2

Day 2: GPIO Input & Interrupts

Today we level up from simple output to reading inputs and handling interrupts. You'll learn to read buttons, handle external interrupts, and build an interactive LED controller.

GPIO Input Modes

  • Pull-up: Internal resistor pulls pin HIGH when button not pressed
  • Pull-down: Internal resistor pulls pin LOW when button not pressed
  • Floating: No internal resistor (requires external pull-up/down)

Reading Button State (Polling)

// Read button state
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
    // Button pressed
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
} else {
    // Button released
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
}

External Interrupts (EXTI)

Interrupts allow the MCU to respond immediately to events without constantly checking (polling). This is more efficient and enables faster response times.

Interrupt Callback

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0) {
        // Toggle LED on button press
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    }
}

Debouncing Techniques

Mechanical buttons "bounce" - they make and break contact multiple times when pressed. We need to debounce to get clean button presses.

uint32_t lastDebounceTime = 0;
uint32_t debounceDelay = 50;  // 50ms

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    uint32_t currentTime = HAL_GetTick();
    
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        if (GPIO_Pin == GPIO_PIN_0) {
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        }
        lastDebounceTime = currentTime;
    }
}

Advanced: Multi-Function Button

Let's build something more sophisticated! We can detect single press, double press, and long press events. Single press toggles the LED, double press activates blink mode, and long press turns everything off. This demonstrates state machines and advanced input handling.

Key Concepts Learned

  • GPIO input configuration (pull-up, pull-down, floating)
  • Polling vs. interrupts
  • External interrupt (EXTI) configuration
  • Debouncing techniques
  • Building interactive applications

Practice Exercises

  • Create a button that cycles through 3 LED brightness levels
  • Implement a "press and hold" feature to gradually increase LED brightness
  • Build a reaction time game where the LED turns on randomly and you measure button press speed
  • Create a combination lock requiring a specific button press sequence to unlock the LED
Day 3

Day 3: Timers & PWM

Timers are the heartbeat of embedded systems. Today we'll master timer interrupts for non-blocking delays and PWM for controlling LED brightness and servo motors.

Understanding Timers

STM32 has multiple timer types: Basic, General-purpose, and Advanced. They can count up/down, generate interrupts, create PWM signals, and measure input signals.

Timer Calculation

// For 1 second interrupt with 72MHz clock:
// Prescaler = 7200 - 1  (72MHz / 7200 = 10kHz)
// Period = 10000 - 1     (10kHz / 10000 = 1Hz = 1 second)

Timer Interrupt for Non-Blocking Blink

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2) {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    }
}

PWM for LED Brightness Control

PWM (Pulse Width Modulation) varies the duty cycle to control average power. Perfect for LED dimming and motor speed control.

// Start PWM
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

// Set brightness (0-100%)
for (int brightness = 0; brightness <= 100; brightness++) {
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, brightness);
    HAL_Delay(20);
}

Servo Motor Control

Servos use PWM with 50Hz frequency. Pulse width determines angle: 1ms = 0°, 1.5ms = 90°, 2ms = 180°.

void setServoAngle(uint8_t angle) {
    // Map angle (0-180) to pulse width (1000-2000 µs)
    uint16_t pulse = 1000 + (angle * 1000 / 180);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse);
}

Input Capture: Frequency Measurement

Input capture allows you to measure pulse width, frequency, decode PWM signals, and read ultrasonic sensors. Configure TIM4 Channel 1 in input capture direct mode with prescaler 83 for 1MHz timer frequency. The timer captures the counter value when an input signal changes, allowing precise timing measurements.

Key Concepts Learned

  • Timer architecture and configuration
  • Timer interrupts for non-blocking delays
  • PWM generation and duty cycle control
  • Servo motor control with precise PWM
  • Input capture for frequency and pulse width measurement

Practice Exercises

  • Create a "breathing" LED effect with smooth PWM transitions
  • Control 2 LEDs with different PWM frequencies
  • Build an RGB LED controller using 3 PWM channels
  • Create a servo-based "radar" scanner sweeping from 0 to 180 degrees
Day 4

Day 4: Communication Protocols

Communication is key in embedded systems. Today we'll master UART, I2C, and SPI - the three most common protocols for interfacing with sensors, displays, and other devices.

Protocol Comparison

ProtocolWiresSpeedUse Case
UART2 (TX, RX)9600-115200 bpsSerial communication, debugging
I2C2 (SDA, SCL)100-400 kHzMultiple sensors on same bus
SPI4 (MOSI, MISO, SCK, CS)1-10 MHz+High-speed displays, SD cards

UART Communication

// Send string via UART
char msg[] = "Hello from STM32!\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

// Receive data
uint8_t rxData;
HAL_UART_Receive(&huart1, &rxData, 1, HAL_MAX_DELAY);

I2C Temperature Sensor

#define LM75_ADDRESS 0x48 << 1  // I2C address (shifted for HAL)

// Read temperature
uint8_t tempData[2];
HAL_I2C_Mem_Read(&hi2c1, LM75_ADDRESS, 0x00, 1, tempData, 2, HAL_MAX_DELAY);

// Convert to Celsius
int16_t temp = (tempData[0] << 8) | tempData[1];
float temperature = temp / 256.0;

SPI Display Interface

// Send command to SPI display
void sendCommand(uint8_t cmd) {
    HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET);  // Command mode
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);  // Select device
    HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);    // Deselect
}

Choosing the Right Protocol

Use UART when you need simple point-to-point communication, debugging output to a PC, GPS module communication, or Bluetooth module interfacing. Choose I2C when connecting multiple sensors on one bus, using EEPROMs or RTCs, dealing with limited GPIO pins, or when moderate speed is acceptable. Select SPI for high-speed data transfer, driving displays (OLED, LCD, TFT), SD card communication, or when you have enough GPIO pins available.

Key Concepts Learned

  • UART for serial communication and debugging
  • I2C for multi-device communication
  • SPI for high-speed data transfer
  • Protocol selection based on requirements
  • Real sensor and display interfacing

Practice Exercises

  • Build a UART command interpreter that responds to text commands
  • Create an I2C device scanner that lists all connected devices
  • Display sensor data on an OLED screen using SPI or I2C
  • Build a data logger that records sensor readings via UART
Day 5

Day 5: Advanced Features & Complete Project

Welcome to the final day! We'll explore advanced features like ADC, DAC, DMA, and low power modes. Then we'll build a complete Weather Station project integrating everything you've learned.

Analog-to-Digital Converter (ADC)

ADC converts analog signals (0-3.3V) to digital values (0-4095 for 12-bit ADC). Essential for reading sensors like temperature, light, potentiometers.

// Read ADC value
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint32_t adcValue = HAL_ADC_GetValue(&hadc1);

// Convert to voltage
float voltage = (adcValue * 3.3) / 4095.0;

Digital-to-Analog Converter (DAC)

DAC converts digital values to analog voltages. Used for audio, waveform generation, and analog control signals.

// Generate sine wave
for (int i = 0; i < 360; i++) {
    float sine = sin(i * 3.14159 / 180.0);
    uint32_t dacValue = (uint32_t)((sine + 1) * 2047.5);
    HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacValue);
    HAL_Delay(10);
}

Direct Memory Access (DMA)

DMA transfers data between peripherals and memory without CPU intervention, freeing the CPU for other tasks.

// UART transmit with DMA
char msg[] = "DMA Transfer!\r\n";
HAL_UART_Transmit_DMA(&huart1, (uint8_t*)msg, strlen(msg));

// ADC continuous conversion with DMA
uint16_t adcBuffer[100];
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, 100);

Low Power Modes

STM32 offers multiple power modes: Run mode (highest power, all clocks running), Sleep mode (fast wake-up, CPU off but peripherals on), Stop mode (medium wake-up, most clocks off, low power), and Standby mode (slow wake-up, almost everything off, lowest power). Use Sleep mode for short idle periods, Stop mode for longer idle with quick wake-up needed, and Standby for maximum power saving when wake-up time isn't critical.

Complete Weather Station Project

Let's integrate everything: ADC for temperature sensor, I2C for humidity sensor, UART for data logging, and PWM for fan control.

while (1) {
    // Read temperature (ADC)
    float temp = readTemperature();
    
    // Read humidity (I2C)
    float humidity = readHumidity();
    
    // Log data (UART)
    char buffer[50];
    sprintf(buffer, "Temp: %.1f°C, Humidity: %.1f%%\r\n", temp, humidity);
    HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
    
    // Control fan based on temperature (PWM)
    if (temp > 30) {
        setFanSpeed(100);  // Full speed
    } else if (temp > 25) {
        setFanSpeed(50);   // Half speed
    } else {
        setFanSpeed(0);    // Off
    }
    
    HAL_Delay(5000);  // Update every 5 seconds
}

Introduction to FreeRTOS

FreeRTOS is a real-time operating system for microcontrollers. It enables multitasking, allowing multiple tasks to run "simultaneously."

// Task 1: Blink LED
void vTask1(void *pvParameters) {
    while(1) {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// Task 2: Read sensor
void vTask2(void *pvParameters) {
    while(1) {
        float temp = readTemperature();
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

Key Concepts Learned

  • ADC for analog sensor reading
  • DAC for waveform generation
  • DMA for efficient data transfer
  • Low power modes for battery applications
  • Building complete integrated projects
  • Introduction to FreeRTOS multitasking

Final Challenge

Build a Smart Home Controller with temperature/humidity monitoring, light level detection and automatic lighting, motor control for fans, OLED display for status, UART control interface, data logging to SD card, and low power sleep mode for energy efficiency. Share your projects with the community!

🎉 Congratulations!

You've completed the 5-day STM32 mastery journey! You've learned everything from basic GPIO to advanced features like ADC, DMA, and FreeRTOS. You're now equipped to build professional embedded systems projects.

Next Steps

  • Build your own projects combining multiple concepts
  • Explore advanced topics: CAN bus, USB, Ethernet
  • Learn about low-level register programming
  • Dive deeper into FreeRTOS and real-time systems
  • Join STM32 community forums and share your projects

Share this article