Les interfaces ASCII sont moche par définition. Idéalement, vous avez une sorte de structure de cadre, ce que vous avez peut-être, le $ indique la division entre les cadres et vous dites qu'ils ont 11 caractères de longueur. Si toujours 11 c'est bon, si seulement c'est parfois plus difficile, j'espère qu'il y a un $ au début et 0x0A et ou 0x0D/0x0A à la fin (CR/LF). Normalement, j'ai un module de code qui extrait simplement les octets du port série et les met dans un tampon (circulaire). Le tampon datant des jours où les ports série avaient très peu de tampon à bord, mais encore aujourd'hui, surtout avec les microcontrôleurs, c'est toujours le cas. Puis un autre module de code qui surveille le tampon recherchant des trames. Idéalement, ce tampon est assez grand pour laisser le cadre là et avoir de la place pour la trame suivante et ne pas nécessiter d'autre tampon pour conserver les copies des trames reçues. En utilisant le tampon circulaire, ce second module peut se déplacer (en rejetant si nécessaire) le pointeur de tête vers le début du marqueur de trame et attend une valeur de trame complète de données. Une fois qu'un cadre complet semble être là, il appelle une autre fonction qui traite ce cadre. Cette fonction peut être celle que vous demandez. Et "juste le code" peut être la réponse, vous êtes dans un microcontrôleur, de sorte que vous ne pouvez pas utiliser l'application de bureau haut niveau paresseux sur une solution de système d'exploitation. Vous aurez besoin d'une sorte de fonction strcmp si vous êtes créé vous-même ou disponible dans une bibliothèque, ou non en fonction de votre solution. La force brute si (strncmp (& cadre [1], "bob", 3) == 0) alors, sinon si (strncmp (& frame [1], "ted", 3) alors, sinon si ... Certainement mais vous pouvez mâcher votre rom avec ce genre de choses, ou pas, et le tampon requis pour ce genre d'approche peut mastiquer beaucoup de bélier, ce qui est très lisible, facile à maintenir et portable. (maintenable est normalement en conflit avec fiable et/ou performance), mais cela peut ne pas être un problème, tant que vous pouvez traiter celui-ci avant que le suivant arrive, et ou avant que les données non traitées ne tombent du tampon circulaire. tâche la routine vérificateur de trame peut simplement vérifier que le cadre est bon, je place normalement des marqueurs de début et de fin, la longueur et une sorte de somme de contrôle arithmétique et si c'est un mauvais cadre, il est mis au rebut, cela économise beaucoup de code/corruption des données Lorsque la routine de traitement de trame retourne à la recherche de ves le pointeur de tête pour purger le cadre car il n'est plus nécessaire, bon cadre ou mauvais. Le vérificateur de trame peut seulement valider une trame et la remettre à une autre fonction qui effectue l'analyse. Chaque bloc de lego dans cet arrangement a une tâche très simple, et fonctionne sur la supposition que le bloc de lego au-dessous de lui a exécuté sa tâche correctement. Modulaire, orienté objet, quel que soit le terme que vous voulez utiliser rend la conception, le codage, la maintenance, le débogage beaucoup plus facile. (au prix de la performance et des ressources). Cette approche fonctionne bien pour tout flux de type série soit un port série dans un microcontrôleur (avec suffisamment de ressources) ainsi que des applications sur un bureau regardant des données série à partir d'un port série ou des données TCP qui sont également orientées en série.
Si votre micro n'a pas les ressources pour tout cela, alors l'approche de la machine d'état fonctionne également très bien. Chaque octet qui arrive coïncide avec l'état de la machine d'état. Commencer avec le mode attente en attente du premier octet, est le premier octet a $? ne le jetez pas et revenez au repos. si le premier octet est $ alors passez à l'état suivant. Si vous cherchiez à dire les commandes "et", "ajouter", "ou", et "xor", alors le second état se comparerait à "a", "o" et "x", si aucun de ceux-ci alors aller au ralenti. si un a va alors à un état qui compare pour n et d, si un o va alors à un état qui cherche le r. Si la recherche du r dans ou de l'état ne voit pas le r, alors passez à l'état inactif, si c'est le cas, traitez ensuite la commande, puis passez à l'état inactif. Le code est lisible dans le sens où vous pouvez regarder la machine d'état et voir les mots a, n, d, a, d, d, o, r, x, o, r, et où ils mènent finalement, mais généralement pas considéré comme un code lisible. Cette approche utilise très peu de ram, se penche un peu plus sur la rom mais dans l'ensemble pourrait utiliser le moins de rom par rapport à d'autres approches d'analyse syntaxique.Et là encore est très portable, au-delà des microcontrôleurs, mais en dehors d'un microcontrôleur les gens pourraient penser que vous êtes fou avec ce genre de code (enfin pas si c'était verilog ou vhdl bien sûr). Cette approche est plus difficile à maintenir, plus difficile à lire, mais elle est très rapide et fiable et utilise le moins de ressources.
Peu importe l'approche une fois la commande interprétée, vous devez vous assurer que vous pouvez exécuter la commande sans perdre d'octets sur le port série, soit par des performances déterministes du code ou des interruptions ou quoi que ce soit.
Les interfaces ascii de la ligne de base sont toujours moche, le code pour eux, peu importe le nombre de couches de bibliothèques que vous utilisez pour faciliter le travail, les instructions résultantes qui sont exécutées sont moche. Et une taille ne correspond à personne par définition. Commencez simplement à coder, essayez une machine d'état et essayez le if-then-else-strncmp, et les optimisations entre les deux. Vous devriez voir rapidement quelle est celle qui fonctionne le mieux avec votre style de codage, les outils/processeurs et le problème à résoudre.
Merci! Vos réponses et celles de shodanex ont été de loin les plus utiles pour moi. La machine à états finis semble être le bon choix, même si elle n'est pas aussi intuitive que l'approche modulaire. Et, oui, les interfaces ASCII sont moche. Pas mon choix si: P – Pav