lib C/C++, asyncSerial

on . Posted in Embarqué

 

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:
Librairie en C
Librairie en C++

Utilisation de la librairie en C++

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ères 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 lire les données reçues, il faut utiliser la fonction read(char *outstr, uint8_t length):

char c[MAX_CHARS];
int read_length;
read_length = serial.read(c, LENGTH);    /* LENGTH correspond au nombre de caractère
                                           que vous voulez lire */
                                        /* À la fin, la fonction retourne le nombre
                                           réel de caractères lus; par exemple, si on
                                           veux lire 10 char mais que seuls 3 sont
                                           arrivés la fonction retournera 3 */

On peut également utiliser la fonction ready() pour savoir combien de caractères sont en attente dans le buffer de réception.

int waiting_chars;
waiting_chars = serial.ready(); // Ici la fonction retourne le nombre de char non lu dans le buffer

Utilisation de la librairie en C

void    aserial_Init(long baudrate); /* à exécuter obligatoirement pour
                    initialiser l'UART, ici baudrate n'est pas facultatif */

Pour le reste le fonctionnement est identique à la vertion en C++

uint8_t aserial_Send(CHAR_TYPE *instr, uint8_t length);
uint8_t aserial_Ready();
uint8_t aserial_Read(CHAR_TYPE *outstr, uint8_t length);

Et voilà, bonne utilisation.