usart-reception.c
Le DMA circulaire remplit le tampon UART sans jamais interrompre le CPU : la boucle principale découpe le flux en lignes et exécute les commandes ("led" bascule la LED utilisateur). Le patron de référence pour un mini-protocole série réactif.
Matériel requis
Une Blue Pill STM32F103C8T6 (Cortex-M3 @ 72 MHz, 64 Ko flash) alimentee par micro-USB ou 3,3 V externe ; programmation SWD ou bootloader serie. Terminal série (115200 8N1) envoyant des lignes texte.
Câblage
Aucun câblage : USART2 relié au convertisseur USB de la carte. Activer le DMA RX de USART2 dans CubeMX.
Fonctionnement
Receive_DMA configure un transfert matériel permanent ; __HAL_DMA_GET_COUNTER indique la position d'écriture. La boucle compare à son propre curseur et découpe sur \r/\n.
Exécution
Projet STM32CubeIDE (STM32F103C8) ou Arduino (core STM32) : programmer par SWD (ST-LINK, adaptateur DAPLink) ou par le bootloader serie (BOOT0 a 1). Attention : LED PC13 active LOW.
Variantes
Ajouter des commandes typées (LED, ADC, PWM) façon AT, ou traiter la ligne dans l'callback HAL_UARTEx_RxEventCallback avec DMA half/full.
usart-reception.c
// Reception serie non bloquante : DMA circulaire + recherche de lignes.
#include "main.h"
#include <string.h>
#include <stdio.h>
extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef hdma_usart2_rx;
#define TAILLE 64
uint8_t tampon[TAILLE];
uint16_t dernierIndice = 0;
static void traiterLigne(const char *ligne) {
if (strcmp(ligne, "led") == 0) {
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
} else {
printf("recu: %s\r\n", ligne);
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_DMA_Init();
HAL_UART_Receive_DMA(&huart2, tampon, TAILLE); // ne bloque jamais
for (;;) {
// Le DMA remplit le tampon en tournant ; on lit ce qui a avance.
uint16_t indice = TAILLE - __HAL_DMA_GET_COUNTER(huart2.hdmarx);
while (dernierIndice != indice) {
uint8_t c = tampon[dernierIndice];
dernierIndice = (dernierIndice + 1) % TAILLE;
static char ligne[TAILLE];
static int n = 0;
if (c == '\r' || c == '\n') {
if (n) { ligne[n] = 0; traiterLigne(ligne); n = 0; }
} else if (n < TAILLE - 1) {
ligne[n++] = (char)c;
}
}
}
}