12
Activité : Mise en oeuvre d’un port série sous Qt Thierry Vaira <[email protected]> rev.2 03/04/2017 Table des matières Mise en oeuvre d’un port série sous Qt 1 Présentation Qt ....................................................... 1 Le port série RS-232 .................................................... 2 Le port série virtuel .................................................... 2 Prise en charge matérielle d’un port série ........................................ 2 Gestion du port série sous Qt ............................................... 3 Exemple Qt 4 ..................................................... 3 Exemple Qt 5 ..................................................... 4 Communication ....................................................... 5 Configuration du port ................................................ 6 Émission de trames .................................................. 7 Réception de trames ................................................. 8 Décodage de trames ................................................. 9 Thread d’arrière-plan ................................................. 11 Site : tvaira.free.fr Mise en oeuvre d’un port série sous Qt Présentation Qt Qt est une bibliothèque logicielle orientée objet développée en C++ par Qt Development Frameworks, filiale de Digia. Voir la présentation de Qt. 1

Activité : Mise en oeuvre d'un port série sous Qttvaira.free.fr/projets/activites/activite-port-serie-qt.pdf · Activité : Mise en oeuvre d’un port série sous Qt Thierry Vaira

  • Upload
    others

  • View
    12

  • Download
    0

Embed Size (px)

Citation preview

Activité : Mise en oeuvre d’un port série sous Qt

Thierry Vaira <[email protected]>

rev.2 03/04/2017

Table des matièresMise en oeuvre d’un port série sous Qt 1

Présentation Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Le port série RS-232 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Le port série virtuel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Prise en charge matérielle d’un port série . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Gestion du port série sous Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Exemple Qt 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Exemple Qt 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Configuration du port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Émission de trames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Réception de trames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Décodage de trames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Thread d’arrière-plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Site : tvaira.free.fr

Mise en oeuvre d’un port série sous Qt

Présentation Qt

Qt est une bibliothèque logicielle orientée objet développée en C++ par Qt Development Frameworks, filiale deDigia.

Voir la présentation de Qt.

1

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

Le port série RS-232

RS-232 est une norme standardisant une voie de communication de type série sur trois fils minimum. Disponible sur presquetous les PC depuis 1981 jusqu’au milieu des années 2000, il est communément appelé le « port série ».Sur les systèmes d’exploitation MS-DOS et Windows, les ports RS-232 sont désignés par les noms COM1, COM2, etc. Celaleur a valu le surnom de « ports COM », encore utilisé de nos jours.On utilise maintenant des adaptateurs USB/RS-232 car les PC ne disposent plus d’interfaces physiques RS-232. Celarevient à exploiter logiciellement un port série virtuel. Ces périphériques utilisent en réalité une transmission série avecun convertisseur USB <–> RS-232 (les circuits les plus répandus sont pl2303, FTDI FT232, . . . ). Certains adaptateursajoutent un circuit MAX232 pour mettre en forme des signaux conformes au standard RS-232. La prise en charge dupériphérique est assurée par le système d’exploitation via un pilote de périphérique (driver).Lire le cours sur la transmission série.

Le port série virtuel

Un port série virtuel est une solution logicielle qui émule un port série standard.Cela permet généralement :– d’augmenter le nombre de ports série (sans installation de matériel supplémentaire mais dans les limites des ressourcesdisponibles)

– de partager les données en provenance d’un périphérique entre plusieurs applications– de raccorder un périphérique série standard (RS232, . . . ) sur un port USB avec un adaptateur (manque ou absence deports série physiques disponibles)

De nombreux périphériques USB sont “vus” comme des ports séries virtuels par le système (XBee, Bluetooh, GPS, . . . ).Pour établir une communication effective via un port série physique (RS-232) ou virtuel, il est nécessaire de définir leprotocole utilisé : notamment, le débit de la transmission (en bits/s), le codage utilisé, le découpage en trame, etc. Lanorme RS-232 (couche Physique) laisse ces points libres, mais en pratique on utilise souvent des trames d’un caractèreainsi constituées :– 1 bit de départ (START)– 7 à 8 bit de données– 1 bit de parité optionnel (aucune, paire ou impaire)– 1 ou plusieurs bits d’arrêt (STOP)Remarque : De nombreux périphériques séries expriment encore leur vistesse de transmission en bauds. Le baud est l’unitéde mesure du nombre de symboles transmissibles par seconde. Dans le cas d’un signal modulé utilisé dans le domaine destélécommunications, le baud est l’unité de mesure de la rapidité de modulation. Le terme “baud” provient du patronymed’Émile Baudot, l’inventeur du code Baudot utilisé en télégraphie. Il ne faut donc pas confondre le baud avec le bit parseconde (bit/s) car il est souvent possible de transmettre plusieurs bits par symbole. Si on transmet un bit par symbolealors le baud et le bit par seconde (bit/s) sont équivalents.Exemple : calcul du temps de transmission d’une trame de requête de 8 octets en considérant les paramètres suivants de laliaison série :– Vitesse : 9600 bits/s,– Longueur des données : 8 bits,– Parité : Paire,– Nombre de bits de stop : 1Taille de la trame (en bits) pour transmettre un octet : 1 (START) + 8 (DATA) + 1 (PARITÉ) + 1 (STOP) = 11 bitsTaille de la trame (en bits) pour transmettre une requête : 8 octets x 11 bits = 88 bitsTemps de transmission d’un octet : (1 x 11) / 9600 = 0,00114583 s = 1,14583 msTemps de transmission d’une requête : (8 x 11) / 9600 = 0,00917 s = 9,167 ms

Prise en charge matérielle d’un port série

– Sous Linux– Sous Windows

BTS SN La Salle Avignon 2 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

Gestion du port série sous Qt

Suivant votre version de Qt :– Qt 4 : Malheureusement, la version 4 de Qt ne fournit pas de classes pour gérer un port série nativement. On va doncdevoir utiliser une bibliothèque logicielle externe à Qt : la classe QextSerialPort disponible ici.

– Qt 5 : le problème n’existe plus en Qt5 car on dispose alors de la classe QSerialPort !

Exemple Qt 4

On crée un nouveau répertoire et on se déplace à l’intérieur :� �$ mkdir mo-qextserialport-1

$ cd mo-qextserialport-1/� �On télécharge l’archive :� �$ wget https://github.com/qextserialport/qextserialport/archive/master.zip� �Remarque : vous pouvez utiliser aussi cette archive qextserialport-1.2rc.zip.On décompresse l’archive téléchargée :� �$ unzip master.zip$ rm -f master.zip

$ mv qextserialport-master qextserialport� �On crée un nouveau fichier de projet :� �$ vim mo-qextserialport-1.proinclude(qextserialport/src/qextserialport.pri)

TEMPLATE = appTARGET =DEPENDPATH += .INCLUDEPATH += .

OBJECTS_DIR = ./tmpMOC_DIR = ./tmpDESTDIR = ./bin

# InputSOURCES += main.cpp� �On crée maintenant un programme de test du port série :� �$ vim main.cpp� �� �#include "qextserialport.h"#include <QDebug>

#define PORT "/dev/ttyUSB0"

int main(){

QextSerialPort *port;

// instanciation du port en mode asynchrone -> QextSerialPort::Pollingport = new QextSerialPort(QLatin1String(PORT), QextSerialPort::Polling);

// TODO : paramètrer le port (débit, ...)

// ouverture du port en lecture/écritureport->open(QIODevice::ReadWrite);

BTS SN La Salle Avignon 3 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

qDebug("<debug> etat ouverture port : %d", port->isOpen());

// TODO : réceptionner et/ou envoyer des données

// fermeture du portport->close();qDebug("<debug> etat ouverture port : %d", port->isOpen());

delete port;

return 0;}� �On fabrique et on exécute le programme de test :� �$ qmake

$ make

$ ./bin/mo-qextserialport-1<debug> etat ouverture port : 1<debug> etat ouverture port : 0� �Le paramétrage du port série se fait avec les méthodes suivantes :– setBaudRate()– setParity()– setDataBits()– setStopBits()– . . .Et pour les opération de lecture et d’écriture, on utilisera par exemple les méthodes read() et write().Documentation : QextSerialPort.

Exemple Qt 5

On crée un nouveau répertoire et on se déplace à l’intérieur :� �$ mkdir mo-qserialport-1

$ cd mo-qserialport-1/� �On crée un nouveau fichier de projet :� �$ vim mo-qserialport-1.pro

QT += serialport

TEMPLATE = appTARGET =DEPENDPATH += .INCLUDEPATH += .

OBJECTS_DIR = ./tmpMOC_DIR = ./tmpDESTDIR = ./bin

# InputSOURCES += main.cpp� �On crée maintenant un programme de test du port série :� �$ vim main.cpp� �

BTS SN La Salle Avignon 4 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

� �#include <QSerialPort>#include <QDebug>

#define PORT "/dev/ttyUSB0"

int main(){

QSerialPort *port;

// instanciation du portport = new QSerialPort(QLatin1String(PORT));

// TODO : paramètrer le port (débit, ...)

// ouverture du portport->open(QIODevice::ReadWrite);qDebug("<debug> etat ouverture port : %d", port->isOpen());

// TODO : réceptionner et/ou envoyer des données

// fermeture du portport->close();qDebug("<debug> etat ouverture port : %d", port->isOpen());

delete port;

return 0;}� �On fabrique et on exécute le programme de test du port série :� �$ qmake

$ make

$ ./bin/mo-qserialport-1<debug> etat ouverture port : 1<debug> etat ouverture port : 0� �Le paramétrage du port série se fait avec les méthodes suivantes :– setBaudRate()– setParity()– setDataBits()– setStopBits()– . . .Et pour les opération de lecture et d’écriture, on utilisera par exemple les méthodes read() et write().Documentation : QSerialPort.

Communication

De nombreux périphériques utilisent un protocole de communication de type ASCII pour échanger des trames. Il existedes protocoles propriétaires et/ou standardisés. Certains sont très répandus : NMEA 0183 (GPS, station météo, . . . ),commandes AT (modem, XBee , Bluetooth, . . . ).

BTS SN La Salle Avignon 5 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

Cela revient :– à réceptionner et/ou envoyer des trames : on utilisera les services de la classe QextSerialPort (Qt4) ou QSerialPort (Qt5)– à décoder ces trames (vérification, extraction des données, . . . ) : on utilisera les services de la classe QString de Qt.Remarque : Transmettre des données en ASCII permet de s’affanchir du problème de la réprensation des données enmémoire (voir little endian et big endian sur wikipedia).Dans une communication, on distinguera trois types de trame :– les trames périodiques– les trames apériodiques (envoyées sur un évènement ou un changement d’état)– les trames de requête et de réponseLa gestion de la communication va ensuite dépendre de l’architecture de votre application. Si votre application disposed’une IHM, vous ne pourrez pas effectuer d’appels bloquants à partir du thread GUI (Graphical User Interface), qui est lefil d’exécution principal, sinon l’application risquerait de se “figer”. Le thread GUI est responsable de l’affichage et desinteractions avec l’utilisateur et surtout c’est le seul thread qui doit modifier l’affichage.En résumé, cela revient :– soit à gérer le port en mode synchrone à partir du thread GUI en utilisant les signaux readyRead() pour la réception et

bytesWritten() pour l’émission– soit à gérer le port en mode asynchrone à partir d’un autre thread qui communiquera par signal/slot avec le thread GUI

Configuration du port

– En Qt 4 :� �// instanciation du port en mode synchrone -> QextSerialPort::EventDrivenQextSerialPort *port = new QextSerialPort(portName, QextSerialPort::EventDriven);

// configurationport->setBaudRate(BAUD9600);port->setDataBits(DATA_8);port->setParity(PAR_NONE);port->setStopBits(STOP_1);port->setFlowControl(FLOW_OFF);//port->setTimeout(500);

// ouvertureport->open(QIODevice::ReadWrite);

BTS SN La Salle Avignon 6 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

// ...

// fermetureport->close();� �– En Qt 5 :� �// instanciation du portQSerialPort *port = new QSerialPort(portName);

// configurationport->setBaudRate(QSerialPort::Baud9600);port->setDataBits(QSerialPort::Data8);port->setParity(QSerialPort::NoParity);port->setStopBits(QSerialPort::OneStop);port->setFlowControl(QSerialPort::NoFlowControl);

// ouvertureport->open(QIODevice::ReadWrite);

// ...

// fermetureport->close();� �Émission de trames

Remarque : L’émission est généralement plus simple à mettre en oeuvre que la réception.L’émission de trames périodiques peut se faire sous Qt avec un QTimer (i.e. un minuteur ou temporisateur). Le principe estle suivant :� �// instancie un objet QTimerQTimer *timer = new QTimer(this);

// connecte le signal timeout() au slot envoyer()connect(timer, SIGNAL(timeout()), this, SLOT(envoyer()));

// démarre le timer (la période s'expime en millisecondes)timer->start(1000); // toutes les secondes

// ...

// arrête le timerif(timer->isActive()){

timer->stop();}� �À l’expiration du timer le signal timeout()sera émis et le slot envoyer() sera exécuté. Celui-ci devra fabriquer une trame etl’émettre sur le port.Les fonctions d’écriture sont les suivantes :– qint64 write(const char * data, qint64 maxSize)– qint64 write(const char * data)– qint64 write(const QByteArray & byteArray)

Pour les trames apériodiques ou de requête, il suffit d’émettre la trame en utilisant un objet port de type QextSerialPort(Qt4) ou QSerialPort (Qt5) :� �int MaClasse::emettre(const QString &trame){

int nombresOctets = -1;

BTS SN La Salle Avignon 7 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

if (port == NULL || !port->isOpen()){

return -1;}

nombresOctets = port->write(trame.toLatin1());

return nombresOctets;}� �Remarque : Il faudra faire attention à la gestion des tampons (buffers) internes. On rappelle que le traitement fait par unordinateur est beaucoup plus rapide que l’émission d’une trame (nanosecondes vs millisecondes !). Pour de grosses quantitésde données, il faudra se synchroniser avec l’émission sur le périphérique pour éviter la saturation des tampons (buffers)internes.Pour aller plus loin, on dispose :– du signal bytesWritten(qint64 bytes) : ce signal est émis chaque fois bytes octets de données ont été écrits sur lepériphérique.

– de la méthode waitForBytesWritten(int msecs) : elle attend jusqu’à ce que le signal bytesWritten() ait été émis ou quemsecs millisecondes soient passées. Il est déconseillé de l’utiliser à partir du thread GUI.

– de la méthode setTimeout(long millisec) : elle définit les délais d’attente d’écriture (et aussi de lecture) pour le port enmillisec millisecondes. C’est un délai d’expiration par caractère individuel et non pour l’opération entière.

Évidemment, il faudra aussi s’intéresser au contrôle de flux. Le contrôle de flux, dans un réseau informatique, représenteun asservissement du débit binaire des données transmises de l’émetteur vers le récepteur. Le stop and wait est la forme laplus simple de contrôle de flux. En communication série asynchrone RS232, deux modes de contrôle de flux sont proposés :en hardware via les lignes RTS/CTS (Ready To Send/Clear To Send) ou sous contrôle logiciel via les caractères ASCIIXON/XOFF. Le contrôle hardware en RS232 nécessite 5 fils (Rx, Tx, Gnd, RTS, CTS) et le contrôle logiciel n’en nécessiteque 3 (Rx, Tx, Gnd).

Réception de trames

Les fonctions de lecture sont très nombreuses :– qint64 read(char * data, qint64 maxSize)– QByteArray read(qint64 maxSize)– QByteArray readAll()– qint64 readLine(char * data, qint64 maxSize)– QByteArray readLine(qint64 maxSize = 0)

La classe QextSerialPort (Qt4) ou QSerialPort (Qt5) fournit le signal readyRead(). Ce signal est émis une fois que denouvelles données sont disponibles pour la lecture à partir du périphérique.Il faut donc tout d’abord le connecter à un slot de réception :� �void MaClasse::ouvrirPort(const QString &portName){

port = new QextSerialPort(portName, QextSerialPort::EventDriven);// configuration du port ...

if (port->open(QIODevice::ReadWrite) == true){

// on connecte le signal readyRead() au slot recevoir()connect(port, SIGNAL(readyRead()), this, SLOT(recevoir()));

}}� �Puis, le principe de réception de trame à partir d’un thread GUI sera le suivant :� �void MaClasse::recevoir(){

QByteArray donnees;

while (port->bytesAvailable()){

donnees += port->readAll();

BTS SN La Salle Avignon 8 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

usleep(100000); // cf. timeout}

QString trameRecue = QString(donnees.data());

// ....}� �Décodage de trames

La classe QString contient de nombreuses méthodes pour manipuler des chaînes de caractère. Il vous faudra consulter trèssouvent sa documentation : doc.qt.io/qt-4.8/qstring.html.Remarque : la documentation de Qt est très riche et très bien faite !Pour le traitement d’une trame, les méthodes les plus utilisées sont :– startsWith() et endsWith() pour vérifier les délimiteurs de début de trame (par exemple le dollar $) et de fin de trame(par exemple la séquence “\r\n”)

– contains() ou count() pour détecter (ou compter) la présence de certains caractères (le plus souvent des délimiteurscomme la virgule ,, le point-virgule ; ou l’étoile *)

– section() ou split() pour le découpage à partir de délimiteurs (comme la virgule ,, le point-virgule ; . . . ) ou mid()pour une extraction sans délimiteur

– replace() pour le remplacement et remove() pour la suppression de caractères– indexOf() pour obtenir la position d’un caractèreVoici quelques exemples d’utilisation de la classe QString dans le cadre d’un traitement d’une trame NMEA 0183 :� �#include <QDebug>#include <QString>

int main(int argc, char *argv[]){

QString phrase = "$GPGGA,064036.289,4836.5375,N,00740.9373,E,1,04,3.2,200.2,M,,,,0000*0E";// Faire des essais ://QString phrase = "";//QString phrase = "GPGGA,064036.289,4836.5375,N,00740.9373,E,1,04,3.2,200.2,M,,,,0000*0E";//QString phrase = "$GPAAM,A,A,0.10,N,WPTNME*32";//QString phrase = "$GPGGA,064036.289,4836.5375,N,00740.9373,E,1,04,3.2,200.2,M,,,,0000";

QString checksum;const QString debutTrame = "$";const QString typeTrame = "GPGGA";const QString debutChecksum = "*";

// phrase vide ?if(phrase.length() != 0){

// est-ce une phrase NMEA 0183 ?if(phrase.startsWith(debutTrame)){

// est-ce la bonne phrase ?if(phrase.startsWith(debutTrame + typeTrame)){

// y-a-t-il un checksum ?if(phrase.contains(debutChecksum)){

checksum = phrase.section(debutChecksum, 1, 1);qDebug() << "checksum : 0x" << checksum;

}else

qDebug() << "Attention : il n'y a pas de checksum dans cette phrase !";}else

qDebug() << "Erreur : ce n'est pas une trame GGA !";}

BTS SN La Salle Avignon 9 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

elseqDebug() << "Erreur : ce n'est pas une trame NMEA 0183 !";

}else

qDebug() << "Erreur : phrase vide !";

return 0;}� �Généralement, les protocoles intègrent dans la trame un processus de détection d’erreurs de transmission appelée sommede contrôle (checksum), cf. ci-dessous.Une fois la trame vérifiée et découpée, il faudra sans doute assurer la conversion vers des données numériques (int,double, . . . ) :� �#include <QDebug>#include <QString>

int main(int argc, char *argv[]){

/* Exemple de base */int i = 2;double d = 3.14;

// Du numérique -> chaîne de caractèresQString entier = QString::number(i); // int -> QStringQString reel = QString::number(d); // double -> QString//QString reel = QString::number(d, 'f', 1); // double -> QString (avec un chiffre après la virgule)

qDebug() << "L'entier i : " << entier;qDebug() << "Le réel d : " << reel;

// De chaîne de caractères -> numériqueentier = "100";reel = "2.71828";i = entier.toInt(); // QString -> intd = reel.toDouble(); // QString -> double

qDebug() << "L'entier i : " << i;qDebug() << "Le réel d : " << d;

/* Exemple appliqué */QString phrase = "$GPGGA,064036.289,4836.5375,N,00740.9373,E,1,04,3.2,200.2,M,,,,0000*0E";QString horodatage;unsigned int heure, minute;double seconde;

// découpe la trame avec le délimiteur ',' et récupère le deuxième champhorodatage = phrase.section(',', 1, 1);// découpe une chaine à partir d'une position et un nombre de caractèresheure = horodatage.mid(0, 2).toInt();minute = horodatage.mid(2, 2).toInt();seconde = horodatage.mid(4, 2).toDouble();

qDebug() << "Horodatage : " << horodatage;

horodatage = QString::number(heure) + " h " + QString::number(minute)+ " " + QString::number(seconde) + " s";

qDebug() << "Horodatage : " << horodatage;

return 0;}� �Remarque : on peut aussi utiliser la méthode arg() (voir ci-dessous).Un dernier exemple qui montre le calcul du checksum pour une trame NMEA 0183 :

BTS SN La Salle Avignon 10 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

� �#include <QDebug>#include <QString>

unsigned char Simulation::calculerChecksum(QString data){

unsigned char checksum = 0;

// remarque : le dollar n'entre pas dans le calcul du checksumfor(int i=1;i<data.length() && data.at(i).toAscii() != '*';i++){

checksum ^= data.at(i).toAscii(); // XOR}//qDebug("(checksum) 0x%02X\n", checksum);

return checksum;}

int main(int argc, char *argv[]){

QString phrase = "$GPGGA,064036.289,4836.5375,N,00740.9373,E,1,04,3.2,200.2,M,,,,0000";

checksum = calculerChecksum(phrase);

// formate le checksum en ASCII sous la forme hexadécimalestrChecksum = QString("%1").arg(checksum, 2, 16, QLatin1Char('0'));

phrase += QString("*"); // ajoute le délimiteur de checksumphrase += strChecksum.toUpper(); // ajoute le checksum converti en majusculephrase += QString("\r\n"); // ajoute le délimiteur de fin

// ...

return 0;}� �Thread d’arrière-plan

Il est possible de confier la gestion du port à un thread d’arrière-plan.Qt fournit la classe QThread pour la création et manipulation d’un thread. Cette classe possède une méthode run() quicontiendra le code exécuté par le thread. Cette classe émet le signal started() lorsqu’un thread est lancé et finished()lorsque le thread est terminé. Il y a plusieurs approches possibles dans l’utilisation de QThread, en voici deux :– on dérive une classe de QThread et on implémente la fonction run() qui contiendra le code du thread.� �#include <QThread>class Communication : public QThread{

Q_OBJECTpublic:

Communication(QObject * parent = 0);void run(); // le code du thread

private:

signals:

public slots:};

// le code du threadvoid Communication::run(){

QextSerialPort *port = new QextSerialPort(portName, QextSerialPort::Polling);

while(isRunning())

BTS SN La Salle Avignon 11 / 12 © 2017 tv <[email protected]>

MISE EN OEUVRE D’UN PORT SÉRIE SOUS QT

{// ...

}}

Communication *communication = new Communication;

// on démarre le threadcommunication->start(); // cela exécutera dans un thread la méthode run() de la classe Communication� �– pour exécuter du code dans un nouveau thread, on instancie directement un QThread et on assigne les objets héritantde QObject à ce thread en utilisant la fonction moveToThread(). On connecte le started() à un slot de cet objet pourexécuter le code du thread.� �

Acquisition *acquisition = new Acquisition;QThread *threadAcquisition = new QThread;acquisition->moveToThread(threadAcquisition);

QObject::connect(threadAcquisition, SIGNAL(started()), acquisition, SLOT(main()));QObject::connect(threadAcquisition, SIGNAL(finished()), acquisition, SLOT(terminer()));

// on démarre le threadthreadAcquisition->start(); // cela exécutera dans un thread la méthode main() de la classe Acquisition

// ...� �Lire les Threads sous Qt.Retour au sommaire

BTS SN La Salle Avignon 12 / 12 © 2017 tv <[email protected]>