Une utilisation non bloquante de l’UART

Voici une petite librairie que j’ai écrite pour les microcontrôleurs ATMEGAx8 (48, 88, 168, 328).

Elle permet d’utiliser l’UART du micro de manière transparente comme n’importe quelle autre librairie du même genre le fait. La différence avec celle ci, c’est que le programme ne reste pas bloqué sur la fonction « send() » pendant plusieurs précieux milliers de cycles à attendre que les bits soient écrits sur la ligne physique. À la place, la fonction « send() » écrit le tableau de caractères passé en paramètre dans un buffer de type FIFO (First In First Out) puis rend la main au programme principal, permettant ainsi de faire tout un tas de choses en parallèle.

L’astuce vient du fait que, de base, ces microcontrôleurs (et bien d’autres) disposent de périphériques internes dont le rôle est d’alléger la charge du CPU en effectuant d’autres tâches simultanément. Notamment ici, le périphérique UART qui sert à gérer la liaison série de manière autonome.

Comme l’UART n’est quand même pas si autonome que ça, j’utilise les interruption de fin de transmission et fin de réception pour charger dans le transmetteur le prochain caractère de la file d’attente, et mettre dans le buffer de réception le caractère qui vient d’être reçu. Grâce à ces interruptions, le programmeur peut écrire tranquillement son code sans se soucier de gérer les émission et réception, la librairie se charge de tout.

Fini l’attente inutile, À vous le temps CPU libre pour exprimer votre créativité.

Liens de téléchargement:
« serial.h »
« serial.cpp »

Utilisation

Tout d’abord, instacier un objet « uart »:

uart serial(BAUDRATE);    // BAUDRATE est le débit de l'UART

On peut se passer de l’argument BAUDRATE, dans ce cas c’est par défaut réglé à 9600 bps.

Ensuite pour envoyer des caractères:

char c[MAX_CHARS];
serial.send(c, length);   /* c -> tableau de char à envoyer,
                          /* length -> nombre de char à envoyer */

Beaucoup de fonctions utilisant des chaines de caractères ne demandent pas le paramètre « length ». Ces fonctions se basent sur le caractère NULL (ASCII = 0) qui habituellement indique une fin de chaine. Dans le cas d’une UART, ce n’est pas forcément des caractère qui sont envoyés, auquel cas la donnée ZERO est une donnée utile et ne peut donc pas servir de délimiteur de chaine.

Pour recevoir les données reçues, il faut aller lire la FIFO « rx_buffer » en lui donnant en paramètre une adresse où retourner le premier caractère disponible dans le buffer. Si le buffer est vide, le caractère lu sera égal à 0, et la fonction (de type « unsigned char ») retournera également zéro.
Pour lire tous les caractères reçus, on peut donc écrire:

char c[MAX_CHARS];
int i;
while(rx_buffer.out(c + i++));    /* Tant que la fonction ne retourne 
                                  /* pas zéro, on continu à lire le 
                                  /* buffer */

Il suffit ensuite de simplement lire « i – 1 » pour connaitre le nombre de caractères lus.
NOTE: « rx_buffer » est déjà défini dans la librairie.

Et voilà, bonne utilisation.

2 Responses to "Une utilisation non bloquante de l’UART"

  • Mootronic says:
    • Muphins says:
Leave a Comment