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
0si les chaînes sont identiques - Retourne une valeur négative si
chaine1précèdechaine2 - Retourne une valeur positive si
chaine1suitchaine2
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.