Complete guide to ST's ARM Cortex-M based MCUs - From ultra-low-power to high-performance applications
STMicroelectronics' STM32 family of 32-bit ARM Cortex-M microcontrollers offers a comprehensive range of performance, power efficiency, and integration options.
STM32 microcontrollers are organized into several series targeting different application needs:
| Series | Core | Max Freq | Key Features | Target Applications |
|---|---|---|---|---|
| STM32L0/L1 | Cortex-M0+/M3 | 32MHz | Ultra-low-power, LCD | Battery-powered devices |
| STM32F0 | Cortex-M0 | 48MHz | Cost-sensitive, 16-bit legacy | Consumer, industrial |
| STM32G0 | Cortex-M0+ | 64MHz | Value line, USB PD | USB-C, smart devices |
| STM32F1/F2/F3 | Cortex-M3 | 72MHz | Mainstream, analog | General purpose |
| STM32F4 | Cortex-M4 | 180MHz | DSP, FPU, Ethernet | Audio, motor control |
| STM32F7/H7 | Cortex-M7/M4 | 550MHz | Dual-core, TFT, Chrom-ART | GUI, advanced control |
| STM32WB | Cortex-M4/M0+ | 64MHz | Bluetooth 5.0, Zigbee | Wireless IoT |
| STM32WL | Cortex-M4/M0+ | 48MHz | Sub-GHz LPWAN | LoRa, Sigfox |
Development boards make it easy to evaluate and prototype with STM32 microcontrollers:
Affordable development board with Arduino connectivity
High-performance board with TFT display
Ultra-low-power board with Bluetooth
Wireless dual-core board with BLE/Zigbee
The STM32F4 series features ARM Cortex-M4 cores with DSP instructions and floating-point unit (FPU).
| Peripheral | Features | Use Cases |
|---|---|---|
| GPIO | Up to 140 I/Os, interrupt capability | General I/O, external interrupts |
| Timers | 16/32-bit, PWM, encoder interface | Motor control, measurement |
| ADC/DAC | 12-bit, 2.4MSPS, 24 channels | Sensor reading, audio |
| USART/UART | Up to 6 interfaces, LIN/IRDA | Serial communication |
| SPI/I2C | Up to 6/4 interfaces | Sensors, displays, memory |
| USB OTG | FS/HS with PHY | Device/Host communication |
| Memory Type | Address Range | Size | Description |
|---|---|---|---|
| Flash | 0x0800 0000 | Up to 2MB | Program memory |
| SRAM | 0x2000 0000 | Up to 384KB | Data memory |
| Peripherals | 0x4000 0000 | - | AHB/APB bus access |
| System | 0xE000 0000 | - | Cortex-M core peripherals |
// Blink LED on PA5 using HAL
#include "stm32f4xx_hal.h"
int main(void) {
HAL_Init();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
while(1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(500);
}
}
DMA allows peripheral-to-memory transfers without CPU intervention:
// ADC with DMA Example
void ADC_DMA_Init() {
// Configure ADC
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
HAL_ADC_Init(&hadc1);
// Configure DMA
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
HAL_DMA_Init(&hdma_adc1);
// Link DMA to ADC
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
// Start ADC with DMA
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_BUF_LEN);
}
STM32 timers can generate complex PWM signals:
// PWM Output on TIM1 Channel 1
void PWM_Init() {
TIM_HandleTypeDef htim1;
TIM_OC_InitTypeDef sConfigOC = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 84-1; // 1MHz clock
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1000-1; // 1kHz PWM
HAL_TIM_PWM_Init(&htim1);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 50% duty
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
STM32 works well with real-time operating systems:
// Simple FreeRTOS Example
void Task1(void *pvParameters) {
while(1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void Task2(void *pvParameters) {
while(1) {
// Process sensor data
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
xTaskCreate(Task1, "LED_Task", 128, NULL, 1, NULL);
xTaskCreate(Task2, "Sensor_Task", 256, NULL, 2, NULL);
vTaskStartScheduler();
while(1);
}