This project demonstrates how to toggle a green LED connected to a GPIO pin using STM32 HAL functions with the STM32CubeIDE development environment. The LED blinks with a 500 ms delay interval.
- Development Board: STM32 Nucleo-F446RE
- Microcontroller: STM32F446RE (ARM Cortex-M4)
- LED Pin: Custom GPIO (e.g.,
green_led_Pin
onGPIOA
) - Power Supply: USB connection
- IDE: STM32CubeIDE
- Toolchain: STM32 HAL (Hardware Abstraction Layer)
- Language: C
The LED is toggled on and off every 500 milliseconds in the main loop.
HAL_GPIO_WritePin(green_led_GPIO_Port, green_led_Pin, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(green_led_GPIO_Port, green_led_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
The pin is configured as:
GPIO_InitStruct.Pin = green_led_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(green_led_GPIO_Port, &GPIO_InitStruct);
This project demonstrates how to control multiple LEDs connected to GPIO pins on an STM32 Nucleo-F446RE board using STM32 HAL. The LEDs blink in a forward and backward sequence, creating a simple "running light" or "bouncing" LED animation.
- Development Board: STM32 Nucleo-F446RE
- LEDs: 4 LEDs connected to GPIOA (Red, Green, Yellow, Blue)
- Power Supply: USB connection
- IDE: STM32CubeIDE
- Toolchain: STM32 HAL
- Language: C
This code toggles 4 LEDs in the following sequence:
- Forward: Yellow β Blue β Green β Red
- Backward: Green β Blue
Each LED lights up for 200 milliseconds before turning off and moving to the next in the sequence. This creates a simple back-and-forth animation pattern.
for (i = 0; i < 4; i++) {
HAL_GPIO_WritePin(LED_PORT, leds[i], 1);
HAL_Delay(200);
HAL_GPIO_WritePin(LED_PORT, leds[i], 0);
}
for (i = 2; i > 0; i--) {
HAL_GPIO_WritePin(LED_PORT, leds[i], 1);
HAL_Delay(200);
HAL_GPIO_WritePin(LED_PORT, leds[i], 0);
}
LED Color | Pin Macro | Port |
---|---|---|
Red | red_led_Pin |
GPIOA |
Green | green_led_Pin |
GPIOA |
Yellow | yellow_led_Pin |
GPIOA |
Blue | blue_led_Pin |
GPIOA |
These pins are initialized as push-pull output without pull-up or pull-down resistors.
GPIO_InitStruct.Pin = red_led_Pin | green_led_Pin | yellow_led_Pin | blue_led_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
This STM32CubeIDE project demonstrates how to use a push button to increment a counter and control multiple LEDs connected to GPIO pins on the STM32 Nucleo-F446RE board. The number of active LEDs increases with each button press, cycling through four stages.
- Board: STM32 Nucleo-F446RE
- Microcontroller: STM32F446RE (ARM Cortex-M4)
- Input: 1 Push Button (Pull-up enabled)
- Output: 4 LEDs (connected to GPIOA pins PA6, PA7, PA9, PA8)
- Status LED:
green_led_Pin
for button press indication
- IDE: STM32CubeIDE
- Toolchain: STM32 HAL (Hardware Abstraction Layer)
- Language: C
- The program monitors a button connected to a GPIO pin (
button_Pin
) with pull-up enabled. - When the button is pressed (logic low), a counter (
buttonCounter
) is incremented. - The green LED is turned ON while the button is pressed.
- Based on the modulo of the counter (
buttonCounter % 4
), a set number of LEDs are turned ON:- 0 β 1 LED ON (PA6)
- 1 β 2 LEDs ON (PA6, PA7)
- 2 β 3 LEDs ON (PA6, PA7, PA9)
- 3 β 4 LEDs ON (PA6, PA7, PA9, PA8)
- After 4 presses, the counter resets to the beginning of the cycle.
if (buttonCounter % 4 == 0) {
LED1 = ON
} else if (buttonCounter % 4 == 1) {
LED1, LED2 = ON
} else if (buttonCounter % 4 == 2) {
LED1, LED2, LED3 = ON
} else if (buttonCounter % 4 == 3) {
LED1, LED2, LED3, LED4 = ON
}
Purpose | GPIO Pin |
---|---|
Button Input | button_Pin (with pull-up) |
Status LED | green_led_Pin (GPIOA) |
Output LEDs | PA6 , PA7 , PA9 , PA8 |
These pins are configured as follows:
Input (button): GPIO_MODE_INPUT
, GPIO_PULLUP
Output (LEDs): GPIO_MODE_OUTPUT_PP
, GPIO_NOPULL
, MEDIUM
speed
This STM32CubeIDE project demonstrates the use of external interrupts (EXTI) on the STM32 Nucleo-F446RE board. A user button triggers an interrupt that causes a faster LED blinking sequence in addition to the default blinking pattern.
- Board: STM32 Nucleo-F446RE
- Microcontroller: STM32F446RE (ARM Cortex-M4)
- Input: Push Button connected to
PC13
(default user button) - Output: LED connected to custom GPIO pin (
led_Pin
)
- IDE: STM32CubeIDE
- Toolchain: STM32 HAL
- Language: C
- The LED toggles every 500 ms by default.
- When the user presses the button (attached to
PC13
), an external interrupt (EXTI) is triggered. - The interrupt sets a flag
interruptFlag
. - In the next loop cycle, the LED blinks rapidly 5 times (100 ms interval) as a response to the interrupt.
// Default blink every 500 ms
HAL_GPIO_TogglePin(led_GPIO_Port, led_Pin);
HAL_Delay(500);
// On interrupt
if (interruptFlag) {
interruptFlag = 0;
for (int i = 0; i < 5; i++) {
HAL_GPIO_TogglePin(led_GPIO_Port, led_Pin);
HAL_Delay(100);
}
}
Button Pin: buton_Pin
mapped to PC13
Trigger: Rising edge (GPIO_MODE_IT_RISING
)
Pull Configuration: Pull-up enabled (GPIO_PULLUP
)
Interrupt Handler: HAL_GPIO_EXTI_Callback()
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_13) {
interruptFlag = 1;
}
}
Purpose | Pin | Mode |
---|---|---|
LED Output | led_Pin |
GPIO_MODE_OUTPUT_PP |
Button Input | PC13 |
GPIO_MODE_IT_RISING |
This STM32CubeIDE project demonstrates basic UART communication using the STM32 Nucleo-F446RE board. The system waits for a 5-byte message over UART and responds with a predefined message once received.
- Board: STM32 Nucleo-F446RE
- Communication Interface: UART2 (TX/RX)
- Optional Output: LED (status or activity indicator)
- IDE: STM32CubeIDE
- Toolchain: STM32 HAL
- Language: C
- Initializes UART2 at 115200 baud rate.
- Waits for a 5-byte message via UART (blocking mode).
- Once the message is received, it transmits
"Hello!\r\n"
back over UART.
uint8_t messageTX[] = "Hello! \r\n";
uint8_t messageRX[5];
if (HAL_UART_Receive(&huart2, messageRX, sizeof(messageRX), HAL_MAX_DELAY) == HAL_OK) {
HAL_UART_Transmit(&huart2, messageTX, sizeof(messageTX), HAL_MAX_DELAY);
}
Parameter | Value |
---|---|
Baud Rate | 115200 |
Word Length | 8 bits |
Stop Bits | 1 |
Parity | None |
Flow Control | None |
Mode | TX/RX |
UART Function | STM32 Pin | Nucleo Pin Header |
---|---|---|
TX (USART2) | PA2 | D1 |
RX (USART2) | PA3 | D0 |
Open a terminal tool (like PuTTY, TeraTerm, or STM32CubeMonitor).
Connect to the Nucleo board's virtual COM port at 115200 8N1
.
Send any 5-byte string (e.g., 12345
).
You will receive Hello!
as a response over UART.
This STM32 project demonstrates UART-based LED control on the STM32 Nucleo-F446RE board. It allows you to send textual commands (on
, off
, or blink <time>
) to control an onboard LED through a serial terminal.
- Board: STM32 Nucleo-F446RE
- Peripheral Used: UART2 (TX/RX), GPIO (LED Control)
- IDE: STM32CubeIDE
- Library: STM32 HAL (Hardware Abstraction Layer)
- Language: C
- Non-blocking UART Reception (Interrupt-based)
- Command Parsing
- LED Control
- Dynamic LED Blink Duration
Command | Description |
---|---|
on |
Turns the LED on |
off |
Turns the LED off |
blink <time> |
Turns on the LED for <time> seconds |
Example: Sending
blink 3
via serial will turn the LED on for 3 seconds.
- UART receive is configured in interrupt mode using
HAL_UART_Receive_IT
. - Incoming characters are accumulated into a buffer until a recognizable command is detected.
- Upon recognizing:
"on"
: LED is turned on"off"
: LED is turned off"blink <time>"
: LED turns on for<time>
seconds, then off
// Example: Handling "blink 2"
if (strncmp(messageBuffer, "blink ", 6) == 0) {
blinkTime = atoi(&messageBuffer[6]); // parse "2"
interruptFlag = 1;
}
The blinking is handled in the main loop using:
if(interruptFlag){
HAL_GPIO_WritePin(led_GPIO_Port, led_Pin, 1);
HAL_Delay(blinkTime * 1000);
HAL_GPIO_WritePin(led_GPIO_Port, led_Pin, 0);
interruptFlag = 0;
}
Function | STM32 Pin | Nucleo Pin |
---|---|---|
TX | PA2 | D1 |
RX | PA3 | D0 |
- Flash the code to your STM32 Nucleo-F446RE.
- Open a serial terminal (e.g., PuTTY, Tera Term).
- Set Baud rate to 115200.
- Send the following commands:
- on
- off
- blink 5
The LED will behave accordingly.
Input buffer size is 10 bytes
.
All commands must fit within the buffer.
The program resets the buffer after each recognized command.
Uses string.h
and stdlib.h
for parsing and comparison.
This project demonstrates Bluetooth communication between an STM32F4 microcontroller and a smartphone using the HM-10 Bluetooth module over USART1. The STM32 receives data sent from the phone and immediately echoes it back, enabling two-way Bluetooth-based serial communication.
- πΆ Bluetooth Module: HM-10 (BLE)
- π Board: STM32 Nucleo-F446RE
- π‘ Communication: UART (USART1)
- π§ Library: STM32 HAL (Hardware Abstraction Layer)
- π² Phone App: Any Bluetooth serial terminal (e.g., Serial Bluetooth Terminal on Android, BLESerial tiny on iOS)
HM-10 Pin | Connects To STM32 |
---|---|
VCC | 3.3V |
GND | GND |
TXD | RX (e.g., PA10 - USART1 RX) |
RXD | TX (e.g., PA9 - USART1 TX) |
β οΈ Note: HM-10 uses 3.3V logic. Do not connect to 5V TX lines directly without a voltage divider or level shifter.
- The HM-10 module is paired with a smartphone.
- Data sent from the phone is received by STM32 via USART1.
- The microcontroller echoes the data back to the phone.
- This forms a simple Bluetooth serial communication loop.
Parameter | Value |
---|---|
Baud Rate | 9600 |
Data Bits | 8 |
Stop Bits | 1 |
Parity | None |
Flow Control | None |
uint8_t message[10];
HAL_UART_Receive(&huart1, message, 10, 1000); // Receive 10 bytes from HM-10
HAL_UART_Transmit(&huart1, message, 10, 1000); // Echo it back to the phone
This project demonstrates how to measure the internal temperature of the STM32 Nucleo-F446RE board using its built-in temperature sensor via ADC1. The temperature is read, converted to degrees Celsius, and sent over USART2 to a serial terminal.
- π» Microcontroller Board: STM32 Nucleo-F446RE
- π‘ Sensor: Internal temperature sensor of STM32F446RE
- π Communication Interface: UART (USART2)
-
The internal temperature sensor provides a voltage (
VSENSE
) proportional to the chip's temperature. -
This voltage is read using the ADC (Analog-to-Digital Converter).
-
The value is converted to Celsius using the formula provided in the STM32 reference manual:
T(Β°C) = ((VSENSE - V25) / Avg_Slope) + 25
Where:
Parameter | Description | Value / Formula |
---|---|---|
VSENSE |
Voltage corresponding to ADC reading | ADC_Value * VSTEP |
V25 |
Voltage at 25Β°C (factory-calibrated) | 0.76 V |
Avg_Slope |
Average slope of the temperature sensor | 2.5 mV/Β°C or 0.0025 V/Β°C |
VSTEP |
Reference voltage used by ADC | 3.3 / 4096 |
The converted temperature is sent every second over UART using HAL_UART_Transmit()
.
Example output seen in a serial terminal:

while (1) {
temperature = readTemperature(&adcValue);
sprintf(buffer, "Temperature: %.2f Β°C\r\n", temperature);
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
HAL_Delay(1000);
}
Peripheral | Parameter | Value |
---|---|---|
ADC1 | Channel | ADC_CHANNEL_TEMPSENSOR |
Resolution | 12-bit |
|
Sample Time | 112 cycles |
|
Conversion Mode | Single conversion |
|
Trigger | Software start |
|
Continuous Mode | Enabled |
|
Data Alignment | Right |
|
VREF | 3.3V |
|
USART2 | Baud Rate | 115200 |
Word Length | 8 bits |
|
Stop Bits | 1 |
|
Parity | None |
|
Mode | TX/RX |
|
Hardware Flow Ctrl | None |
This project demonstrates how to toggle an LED using STM32F4 microcontroller registers directly without relying on the HAL (Hardware Abstraction Layer) or CMSIS drivers. The LED connected to PA5 (typically the onboard LED on STM32F4 Discovery/Nucleo boards) is toggled with a simple software delay.
- Board: STM32 Nucleo-F446RE
- LED Connection: Onboard LED at GPIOA Pin 5
- IDE: STM32CubeIDE
- No HAL or CMSIS functions used
- Pure register-level programming
- Enables the clock for GPIOA.
- Configures PA5 as:
- Output mode
- Push-pull type
- High-speed
- No pull-up/pull-down
- Enters an infinite loop:
- Sets PA5 high (turn LED on)
- Waits using a crude software delay loop
- Sets PA5 low (turn LED off)
- Waits again
RCC->AHB1ENR |= (1<<0); // Enable clock to GPIOA
GPIOA->MODER &= ~(3<<(5*2)); // Clear mode bits for PA5
GPIOA->MODER |= (1<<(5*2)); // Set PA5 as output (01)
GPIOA->OTYPER &= ~(1<<5); // Push-pull output
GPIOA->OSPEEDR |= (3<<(5*2)); // High speed
GPIOA->PUPDR &= ~(3<<(5*2)); // No pull-up/pull-down
GPIOA->ODR |= (1<<5); // LED ON
for (int i = 0; i < 1000000; ++i); // Delay
GPIOA->ODR &= ~(1<<5); // LED OFF
for (int i = 0; i < 1000000; ++i); // Delay
- This code uses bare-metal programming: no HAL, no interrupts, no external libraries.
- The LED blinking is based on an inaccurate software delay β use hardware timers for better control.
- PA5 is typically connected to the onboard LED on most STM32F4 boards, but verify your boardβs pinout.
- Smaller binary size
- Maximum control over hardware
- Useful for bootloaders or performance-critical code
- No abstraction: less portable
- More error-prone
- No safety checks
This project demonstrates how to control an LED connected to GPIOA Pin 5 using a button connected to GPIOC Pin 13, implemented at the register level (bare-metal) without using the HAL or CMSIS abstraction layers.
- Development Board: STM32 Nucleo-F446RE
- Button: Connected to PC13 (typically the blue push button on Nucleo boards)
- LED: Connected to PA5 (typically the onboard LED)
- IDE: STM32CubeIDE
- No HAL/CMSIS functions used
- Pure register-level code
- Configures PC13 as a digital input with pull-up resistor.
- Configures PA5 as a digital output.
- Continuously reads the state of the button:
- If the button is pressed (PC13 pulled LOW), the LED on PA5 is turned on.
- If the button is not pressed (PC13 HIGH), the LED is turned off.
RCC->AHB1ENR |= (1 << 2); // Enable clock for GPIOC
GPIOC->MODER &= ~(3 << (13 * 2)); // Set PC13 as input
GPIOC->PUPDR &= ~(3 << (13 * 2)); // Clear pull-up/down bits
GPIOC->PUPDR |= (1 << (13 * 2)); // Enable pull-up
RCC->AHB1ENR |= (1 << 0); // Enable clock for GPIOA
GPIOA->MODER &= ~(3 << (5 * 2)); // Clear PA5 mode bits
GPIOA->MODER |= (1 << (5 * 2)); // Set PA5 as output
GPIOA->OTYPER &= ~(1 << 5); // Push-pull
GPIOA->OSPEEDR |= (3 << (5 * 2)); // High speed
GPIOA->PUPDR &= ~(3 << (5 * 2)); // No pull-up/pull-down
while (1) {
if (!(GPIOC->IDR & (1 << 13))) {
GPIOA->ODR |= (1 << 5); // Turn LED on
} else {
GPIOA->ODR &= ~(1 << 5); // Turn LED off
}
}
- PC13 is connected to the user button on many Nucleo boards.
- No debouncing is implemented β for real-world use, software or hardware debouncing may be required.
- You can easily adapt this example to other pins or external buttons/LEDs.