🔬
TPs STM32F4
11 Projets Pratiques avec HAL
STM32CubeIDE
HAL Library
BTS 2025-2026
TP1 : GPIO Output - LED Clignotante
Configuration CubeMX et HAL
Objectifs pedagogiques
- Creer un projet STM32CubeIDE
- Configurer les GPIO avec CubeMX
- Utiliser HAL_GPIO_WritePin et HAL_GPIO_TogglePin
- Compiler et flasher le programme
Configuration CubeMX
- File - New - STM32 Project
- Selectionner STM32F407VG (Discovery) ou STM32F401RE (Nucleo)
- Pinout: PA5 - GPIO_Output (LED sur Nucleo)
- Clock: HSE 8MHz, SYSCLK 168MHz (F407) ou 84MHz (F401)
- Project Manager - Generate Code
STM32F407 Discovery STM32F401 Nucleo +------------------+ +------------------+ | | | | | LED Verte: PD12 | | LED User: PA5 | | LED Orange: PD13 | | Bouton: PC13 | | LED Rouge: PD14 | | | | LED Bleue: PD15 | | | | | | | | Bouton: PA0 | | | +------------------+ +------------------+
Code HAL - main.c
/* TP1 : Clignotement LED - STM32F4 */ /* USER CODE BEGIN WHILE */ while (1) { // Methode 1 : Toggle HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); HAL_Delay(500); // 500ms /* USER CODE END WHILE */ }
Version avec WritePin
while (1) { // Allumer LED HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(1000); // Eteindre LED HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); HAL_Delay(1000); }
Exercices
- Faire clignoter les 4 LEDs du Discovery en sequence
- Creer un chenillard (Knight Rider)
- Signal SOS en morse
TP2 : GPIO Input et Interruptions
Lecture bouton avec EXTI
Objectifs pedagogiques
- Configurer une entree GPIO avec pull-up/pull-down
- Configurer une interruption externe EXTI
- Implementer le callback d'interruption
- Comprendre le debouncing materiel et logiciel
Configuration CubeMX
- PC13 (Nucleo) ou PA0 (Discovery) - GPIO_EXTI
- GPIO mode: External Interrupt with Rising/Falling edge
- Pull: Pull-up (pour bouton actif bas)
- NVIC: Activer EXTI line[15:10] (ou EXTI0)
Code : Lecture Polling
/* Lecture bouton par polling */ while (1) { if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); HAL_Delay(200); // Anti-rebond } }
Code : Interruption EXTI
/* Callback d'interruption EXTI */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_13) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); } } /* Note: Ne pas utiliser HAL_Delay() dans une IT ! */
Anti-rebond
Pour un debouncing logiciel en interruption, utilisez un timer ou une variable volatile avec timestamp.
TP3 : ADC - Conversion Analogique
Lecture potentiometre et capteurs
Objectifs pedagogiques
- Configurer l'ADC en mode polling
- Configurer l'ADC en mode interruption
- Comprendre la resolution (12 bits = 0-4095)
- Convertir la valeur ADC en tension
Configuration CubeMX
- PA0 - ADC1_IN0
- ADC1 - Enable
- Resolution: 12 bits
- Sampling Time: 84 cycles
Code : ADC Polling
uint32_t adc_value; float voltage; while (1) { HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 100); adc_value = HAL_ADC_GetValue(&hadc1); // Convertir en tension (3.3V ref) voltage = (adc_value * 3.3f) / 4095.0f; HAL_Delay(100); }
Code : ADC avec Interruption
volatile uint32_t adc_value; /* Demarrer conversion en IT */ HAL_ADC_Start_IT(&hadc1); /* Callback fin de conversion */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if (hadc == &hadc1) { adc_value = HAL_ADC_GetValue(&hadc1); HAL_ADC_Start_IT(&hadc1); } }
TP4 : PWM - Modulation de Largeur
Controle LED RGB et servomoteur
Objectifs pedagogiques
- Configurer un timer en mode PWM
- Calculer prescaler et ARR pour la frequence
- Varier le rapport cyclique (CCR)
- Commander une LED RGB et un servomoteur
Configuration CubeMX
- TIM2 - Channel 1 - PWM Generation CH1
- PA5 - TIM2_CH1 (alternate function)
- Prescaler: 84-1 (1MHz avec 84MHz)
- Counter Period (ARR): 1000-1 (1kHz PWM)
Formule PWM
f_PWM = f_CLK / ((PSC+1) x (ARR+1))
Code : PWM pour LED
/* Demarrer PWM */ HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); while (1) { // Augmenter luminosite for (int duty = 0; duty <= 1000; duty += 10) { __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty); HAL_Delay(10); } // Diminuer luminosite for (int duty = 1000; duty >= 0; duty -= 10) { __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty); HAL_Delay(10); } }
Application : Servomoteur
/* Servomoteur : PWM 50Hz, pulse 1-2ms */ // PSC = 84-1, ARR = 20000-1 = 50Hz // CCR = 1000 = 1ms (0 deg) // CCR = 1500 = 1.5ms (90 deg) // CCR = 2000 = 2ms (180 deg) void Servo_SetAngle(uint8_t angle) { uint16_t ccr = 1000 + (angle * 1000) / 180; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, ccr); }
TP5 : UART - Communication Serie
Communication avec PC via terminal
Objectifs pedagogiques
- Configurer UART avec baudrate 115200
- Transmettre des donnees vers le PC
- Recevoir des commandes du PC
- Rediriger printf vers UART
Configuration CubeMX
- USART2 - Asynchronous (connecte au ST-Link)
- Baud Rate: 115200
- Word Length: 8 bits
- Parity: None, Stop Bits: 1
- NVIC: USART2 global interrupt - Enable
Code : Transmission UART
char msg[] = "Hello STM32!\r\n"; /* Transmission bloquante */ HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100); /* Avec sprintf */ char buffer[64]; sprintf(buffer, "ADC = %lu, Temp = %.1f C\r\n", adc_value, temp); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), 100);
Redirection printf
#include <stdio.h> int __io_putchar(int ch) { HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, 100); return ch; } /* Utilisation */ printf("Temperature: %.2f C\r\n", temperature);
Code : Reception UART avec Interruption
uint8_t rx_data; /* Activer la reception */ HAL_UART_Receive_IT(&huart2, &rx_data, 1); /* Callback de reception */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart2) { if (rx_data == '1') HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); else if (rx_data == '0') HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); HAL_UART_Receive_IT(&huart2, &rx_data, 1); } }
TP6 : Timer - Interruptions Periodiques
Base de temps precise
Configuration CubeMX
- TIM3 - Clock Source: Internal Clock
- Prescaler: 8400-1 (pour 10kHz avec 84MHz)
- Counter Period: 10000-1 (pour 1Hz = 1s)
- NVIC: TIM3 global interrupt - Enable
Code : Timer Interrupt
volatile uint32_t seconds = 0; /* Demarrer le timer en mode IT */ HAL_TIM_Base_Start_IT(&htim3); /* Callback d'interruption Timer */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim == &htim3) { seconds++; HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); } } /* Dans main loop */ while (1) { printf("Temps: %lu s\r\n", seconds); HAL_Delay(1000); }
TP7 : I2C - Ecran LCD 16x2
Communication I2C avec peripherique
Configuration CubeMX
- I2C1 - I2C
- PB6 - I2C1_SCL, PB7 - I2C1_SDA
- Speed Mode: Standard (100kHz)
- Clock Speed: 100000
Code : LCD I2C
#define LCD_ADDR (0x27 << 1) void LCD_SendCommand(uint8_t cmd) { uint8_t data[4]; data[0] = (cmd & 0xF0) | 0x0C; data[1] = (cmd & 0xF0) | 0x08; data[2] = ((cmd << 4) & 0xF0) | 0x0C; data[3] = ((cmd << 4) & 0xF0) | 0x08; HAL_I2C_Master_Transmit(&hi2c1, LCD_ADDR, data, 4, 100); } void LCD_Init(void) { HAL_Delay(50); LCD_SendCommand(0x30); HAL_Delay(5); LCD_SendCommand(0x30); HAL_Delay(1); LCD_SendCommand(0x30); LCD_SendCommand(0x20); // 4-bit mode LCD_SendCommand(0x28); // 2 lines LCD_SendCommand(0x0C); // Display ON LCD_SendCommand(0x06); // Entry mode LCD_SendCommand(0x01); // Clear }
TP8 : SPI - Communication Haute Vitesse
Lecture carte SD ou capteur
Configuration CubeMX
- SPI1 - Full-Duplex Master
- PA5 - SCK, PA6 - MISO, PA7 - MOSI
- PA4 - GPIO_Output (CS)
- Prescaler: 16 (pour ~5MHz)
Code : SPI Transmit/Receive
#define CS_LOW() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET) #define CS_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET) uint8_t SPI_Transfer(uint8_t data) { uint8_t rx; HAL_SPI_TransmitReceive(&hspi1, &data, &rx, 1, 100); return rx; } uint8_t SPI_ReadRegister(uint8_t reg) { uint8_t value; CS_LOW(); SPI_Transfer(reg | 0x80); value = SPI_Transfer(0x00); CS_HIGH(); return value; }
TP9 : DMA - Transfert Sans CPU
ADC et UART avec DMA
Configuration CubeMX - ADC avec DMA
- ADC1 - DMA Settings - Add - ADC1
- Mode: Circular
- Data Width: Half Word (16 bits)
- ADC: Continuous Conversion - Enable
Code : ADC avec DMA
uint16_t adc_buffer[100]; /* Demarrer ADC + DMA */ HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, 100); /* Callback transfert complet */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { // Traiter adc_buffer[50..99] } /* Callback demi-transfert */ void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) { // Traiter adc_buffer[0..49] }
TP10 : FreeRTOS - Multitache
Introduction au temps reel
Configuration CubeMX
- Middleware - FreeRTOS - CMSIS_V2
- Tasks and Queues - Add Task
- Task Name: Task_LED, Priority: Normal
- Stack Size: 128 words
Code : Deux Taches FreeRTOS
/* Tache 1 : Clignotement LED */ void Task_LED(void *argument) { for(;;) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); osDelay(500); } } /* Tache 2 : Envoi UART */ void Task_UART(void *argument) { uint32_t count = 0; char msg[32]; for(;;) { sprintf(msg, "Count: %lu\r\n", count++); HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100); osDelay(1000); } }
TP11 : Projet Final - Station Meteo
Integration de tous les concepts
Cahier des charges
- Lire temperature (DHT11) et luminosite (LDR)
- Afficher sur LCD I2C 16x2
- Envoyer donnees via UART vers PC
- Alarme LED si temperature superieure au seuil
- LED RGB pour indiquer le niveau de luminosite
Architecture du Projet
+-----------------------------------------------------------+ | STATION METEO STM32 | +-----------------------------------------------------------+ | +------+ +----------+ +------+ | | |DHT11 |---PA4------| |---PA5----| LED | | | +------+ | | +------+ | | +------+ | STM32F4 | +------+ | | | LDR |---ADC1-----| 401/407 |---TIM2---|LED RGB| | | +------+ | | +------+ | | +----+-----+ | | | | | +----+----+ | | | I2C1 | | | | LCD16x2 | | | +---------+ | | | | | +----+----+ | | | UART2 |--- Terminal PC | | +---------+ | +-----------------------------------------------------------+
Criteres d'evaluation
| Critere | Points |
|---|---|
| Configuration CubeMX correcte | /3 |
| Lecture capteurs fonctionnelle | /4 |
| Affichage LCD | /3 |
| Communication UART | /3 |
| Alarmes et LEDs | /3 |
| Code propre et commente | /2 |
| Rapport de TP | /2 |
| Total | /20 |