Fonctions courantes pour STM32 et débogage avec printf

Fonctions courantes pour STM32 et débogage avec printf

Manipulation de mémoire et chaînes de caractères

Les fonctions de la bibliothèque standard C utilisent le type char * pour les paramètres pointeurs. Ces fonctinos sont déclarées dans l'en-tête <string.h>.

Opérations sur la mémoire

Effacement de tampon avec memset :

memset((char *)bufferReception, 0, TAILLE_BUFFER_REC);

Cette instruction remplit la zone mémoire pointée par bufferReception sur une longueur de TAILLE_BUFFER_REC octets avec la valeur zéro.

Copie de bloc mémoire avec memcpy :

memcpy(destination, source, longueur);

Copie longueur octets depuis l'adresse source vers l'adresse destination. Les deux paramètres sont des pointeurs.

Exemple concret :

memcpy(&tamponReponse[offsetReponse], bufferReception, nbOctetsRecus);

Copie nbOctetsRecus octets depuis bufferReception dans tamponReponse à partir de la position offsetReponse.

Manipulation de chaînes

Recherche dans une chaîne :

strstr((char *)donnees, "+IPD");    // Recherche gauche-droite d'une sous-chaîne
strrchr("repert/fichier", '/');     // Recherche droite-gauche d'un caractère

Comparaison de chaînes avec strcmp :

Cette fonction retourne un entier indiquant la relation entre deux chaînes :

int strcmp(const char *chaine1, const char *chaine2);

  • Retourne 0 si les chaînes sont identiques
  • Retourne une valeur négative si chaine1 précède chaine2
  • Retourne une valeur positive si chaine1 suit chaine2

Découpage de chaîne avec strtok :

char *premierToken = strtok((char *)donnees, ":");   // Premier segment avant ':'
char *deuxiemeToken = strtok(NULL, ":");              // Segment suivant après ':'

Copie de chaîne avec strcpy :

char *strcpy(char *dest, const char *source);

Copie le contenu de source dans dest. Le tampon dest doit disposer d'un espace suffisant. Retourne un pointeur vers dest.

Fonctions de formatage

Utilisations avancées de printf

Affichage d'une sous-chaîne de longueur donnée :

printf("%.*s", nbCaracteres, bufferReception);

Formatage de date avec remplissage :

sprintf(texte, "%04d-%02d-%02d %02d:%02d:%02d",
        date.annee, date.mois, date.jour,
        date.heure, date.minute, date.seconde);

Le spécificateur %04d produit un entier sur 4 chiffres comblés par des zéros.

Affichage hexadécimal avec préfixe :

Utilisez "%#x" pour un préfixe 0x en minuscules, ou "%#X" pour 0X en majuscules.

sprintf — Écriture formatée dans une chaîne

char commande[64];
sprintf(commande, "AT+CIPSEND=%d\r\n", longueurDonnees);

sscanf — Lecture formatée depuis une chaîne

Le spécificateur %* permet d'ignorer des caractères. Par exemple %*7c saute 7 caractères, %*f ignore un flottant.

char tamponRecu[] = "+IPD,3,\"192.168.43.197\",9999:abc";
int longueurData;
char ipDistante[32];
int port;

sscanf(tamponRecu,
       "%*[\r\n]+IPD,%d,\"%[^\"]\",%d",
       &longueurData,
       ipDistante,
       &port);

Le motif %*[\r\n] ignore les retours à la ligne, et %[^\"] capture tous les caractères jusqu'au prochain guillemet.

Implémentation d'un système de débogage

Les appels à printf sont coûteux en temps d'exécution. Il est donc souhaitable de pouvoir les désactiver facilement une fois le débogage terminé.

Activation par condition préprocesseur

#define MODE_DEBUG 1

#if (MODE_DEBUG == 1)
    #define log_info(...) printf(__VA_ARGS__)
#else
    #define log_info(...)
#endif

Macro avec paramètres variadiques

#define log_info(format, ...) printf(format, ##__VA_ARGS__)

Le symbole ## supprime la virgule si aucun argument supplémentaire n'est fourni.

Ajout automatique de saut de ligne

#define log_ligne(format, ...) printf(format "\r\n", ##__VA_ARGS__)

La concaténation de littéraux de chaîne "texte1""texte2" produit "texte1texte2" en C.

Affichage du fichier source et du numéro de ligne

#include <string.h>

#define MODE_DEBUG 1

#if (MODE_DEBUG == 1)

/* Extrait uniquement le nom du fichier depuis le chemin absolu */
#define NOM_FICHIER (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)

#define log_info(format, ...) \
    printf("[%20s:%4d] -- " format, NOM_FICHIER, __LINE__, ##__VA_ARGS__)

#define log_ligne(format, ...) \
    printf("[%20s:%4d] -- " format "\r\n", NOM_FICHIER, __LINE__, ##__VA_ARGS__)

#else

#define log_info(format, ...)
#define log_ligne(format, ...)

#endif

L'identifiant __FILE__ contient le chemin complet du fichier source, __LINE__ donne le numéro de ligne courant. La macro NOM_FICHIER extrait le nom seul en cherchant le dernier séparateur de chemin.

Exemple d'utilisation :

log_ligne("Connexion établie sur le port %d", portEcoute);
log_info("Réponse reçue : %s", tamponReponse);

Pour compiler sans traces de débogage, il suffit de positionner MODE_DEBUG à 0 — toutes les macros de log seront alors remplacées par des instructions vides sans coût mémoire ni processeur.

Étiquettes: STM32 C printf debug préprocesseur

Publié le 2 juin à 05h40