Gestion du port série en C #
L’objectif de ce travail est de gérer des données obtenues via le port série.
Si le port série a peu à peu disparu des PCs de bureau, il est encore largement répandu sur les cartes à micro-contrôleurs ou les machines monocartes types Raspberry. Il peut être aussi émulé sur un port USB, ce qui est maintenant la méthode d’utilisation la plus courante dans laquelle nous allons nous placer.
Votre objectif sera de récupérer des données émises par une carte à microcontrôleur, sur une Raspberry Pi, afin de les stocker.
Lecture ligne par ligne #
Sur le port série, la carte à microcontrôleur émet des lignes de texte. Notre code devra récupérer ces lignes de manière continue et les traiter.
L’ouverture et le réglage du port série étant un peu verbeux en C, une partie du code vous est fournie :
#include <stdio.h>
#include <string.h>
// Linux headers
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
int configure_serial(char * file, int bauds) {
int serial_port = open(file, O_RDONLY);
struct termios tty;
if (serial_port < 0) {
fprintf(stderr, "Erreur à l'ouverture du fichier %s\n", file);
return -1;
}
// Initialisation de la structure tty
if(tcgetattr(serial_port, &tty) != 0) {
fprintf(stderr,"Error %i from tcgetattr: %s\n", errno, strerror(errno));
return -1;
}
tty.c_cflag &= ~PARENB; // Pas de bit de parité
tty.c_cflag &= ~CSTOPB; // 1 bit stop
tty.c_cflag &= ~CSIZE; // 8 bits de données (cleat + set)
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // Désactiver RTS/CTS
tty.c_cflag |= CREAD | CLOCAL; // Activation de la lecture et on ignore les inst. de contrôle
tty.c_lflag |= ICANON; // lecture caractère par caractère et non ligne par ligne
tty.c_lflag &= ~ECHO; // Pas d'écho
tty.c_lflag &= ~ECHOE;
tty.c_lflag &= ~ECHONL;
tty.c_lflag &= ~ISIG; // On n'interpête pas les caractères INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Désactiver le contrôle de flux logiciel
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Pas de traitement des octets de contrôle
// tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
// tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
// tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX)
// tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX)
tty.c_cc[VTIME] = 100; // Lecture bloquante, avec un timeout de 10 secondes (unité : 0.1 s)
tty.c_cc[VMIN] = 0;
// Vitesse
cfsetispeed(&tty, bauds);
//cfsetospeed(&tty, bauds);
// Enregistrement des réglages
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
fprintf(stderr,"Error %i from tcsetattr: %s\n", errno, strerror(errno));
return -1;
}
return serial_port;
}
int main(void) {
// Buffer pour stocker les données lues
// Une ligne ne pourra pas faire plus que 256 caractères
char read_buf [256];
int serial_port;
// Effacement du buffer
memset(&read_buf, '\0', sizeof(read_buf));
// Ouverture du port série
serial_port=configure_serial("/dev/ttyUSB0", B9600);
if (serial_port < 0) return 1;
// La lecture des données est réalisé par un appel à la fonction read
close(serial_port);
return 0;
}
Dans le code qui précède, vous avez juste à compléter la fonction main
, de manière à lire quelques
lignes de texte avec la fonction read
.
Pour compiler et exécuter du code sous Linux, si votre source s’appelle : read_serial_line
:
$ gcc -Wall -o read_serial_line read_serial_line.c
$ ./read_serial_line