Voila les sources de ma bibliothèque :
http://ferdinandpiet...232_pour_qt.rar (j'ai aussi mis le code en fin de post)
Tu ne pourras pas l'utiliser telle quelle, mais au moins, ça te permettra de voir les fonctions de l'api windows que j'ai utilisé.
Les méthodes que tu peux regarder en premier sont :
open(
writeCOM(
readCOM(
ainsi que le constructeur QWinSerialPort( pour la configuration initiale
Ensuite, si tu veux encapsuler tout ça dans unthread pour pouvoir écouter le port série en permanance tout en continuant à exécuter ton programme, il te faudra regarder la gestion des évènements et en particulier les méthodes
receiveData(
run(
Si tu souhaites apprendre le C++, je te conseil ce tuto qui est juste LE meilleur :
http://www.siteduzer...-langage-c.html++
Black Templar
Ci dessous, le code :
QWinSerialPort.h
/********************************************************************************
QWinSerialPort.h :
Classe de base pour l'envoi et la réception de donner sur un port série RS232.
Encapsulation dans un Thread pour le framework Qt
Auteur : Black Templar
********************************************************************************/
#ifndef DEF_QWinSerialPort
#define DEF_QWinSerialPort
#include <windows.h>
#include <QThread>
class QWinSerialPort : public QThread
{
Q_OBJECT
public:
QWinSerialPort(); // Constructeur
~QWinSerialPort(); // Déconstructeur
int getBaudRate(); // Retourne le baud rate
DCB getDCBConfig(); // Retourne la configuration DCB actuelle du port COM
char getEventChar(); // Retourne le caractère qui déclanchera le signal eventCharReceived() lorsqu'il est reçu
int getReadIntervalTimeout(); // Retourne le temps d'attente de la fonction read
bool isOpen(); // Retourne le statut du port
QString read(); // Retourne tout ce qui a été lu depuis le dernier appel de cette méthode
public slots:
bool open(int); // Ouvre un port
bool setBaudRate(int); // Configure le baud rate
bool setDCBConfig(DCB); // Importe une configuration DCB pour le port série
bool setEventChar(char); // Configure le caractère qui déclanchera le signal eventCharReceived() lorsqu'il est reçu
bool setReadIntervalTimeout(int); // Configure le temps d'attente de la fonction read
bool write(QString); // Envoie des données au port
void close(); // Ferme le port
protected:
bool readCOM(void*, int); // Lit les données reçu par le port COM
void receiveData(DWORD); // Remplis le buffer de réception avec les données récupéré par le port COM et lance un signal
void run(); // Active le thread (met le port en mode écoute)
bool writeCOM(void*, int); // Envoie des données au port
private:
QString a_buffer;
COMMTIMEOUTS a_cto; // Configuration du port COM
DCB a_dcb; // Configuration du port COM
HANDLE a_hCOM; // L'identifiant Windows du fichier
bool a_open; // Flag d'ouverture du port
OVERLAPPED a_overlap; // Structure d'erreur du port COM (mode asynchrone)
signals:
void eventCharReceived(); // Signal annonçant l'arrivée du caractère event (Cf DCB conf)
void reading(); // Signal annonçant l'arrivée de données
void error(long); // Signal annonçant une erreur
};
#endif // DEF_QWinSerialPort
QWinSerialPort.cpp
/********************************************************************************
QWinSerialPort.cpp :
Classe de base pour l'envoi et la réception de donner sur un port série RS232.
Encapsulation dans un Thread pour le framework Qt
Auteur : Black Templar
********************************************************************************/
#include "QWinSerialPort.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
/*******************************************************************************
Définition de constantes
*******************************************************************************/
#define RX_SIZE 4096 /* taille tampon d'entrée */
#define TX_SIZE 4096 /* taille tampon de sortie */
#define MAX_WAIT_READ 5000 /* temps max d'attente pour lecture (en ms)
(mode synchrone : non utilisé ici) */
/******************************************************************************
QWinSerialPort : Constructeur.
Initialisation.
******************************************************************************/
QWinSerialPort::QWinSerialPort()
{
/* Handle du port COM ouvert */
a_hCOM = NULL;
/* Délais d'attente sur le port COM */
a_cto.ReadIntervalTimeout = MAX_WAIT_READ;
a_cto.ReadTotalTimeoutMultiplier = 0;
a_cto.ReadTotalTimeoutConstant = MAX_WAIT_READ;
a_cto.WriteTotalTimeoutMultiplier = 0;
a_cto.WriteTotalTimeoutConstant = 0;
/* Configuration du port COM */
a_dcb.DCBlength = sizeof(DCB);
a_dcb.BaudRate = CBR_9600;
a_dcb.fBinary = TRUE;
a_dcb.fParity = FALSE;
a_dcb.fOutxCtsFlow = FALSE;
a_dcb.fOutxDsrFlow = FALSE;
a_dcb.fDtrControl = DTR_CONTROL_ENABLE;
a_dcb.fDsrSensitivity = FALSE;
a_dcb.fTXContinueOnXoff = FALSE;
a_dcb.fOutX = FALSE;
a_dcb.fInX = FALSE;
a_dcb.fErrorChar = FALSE;
a_dcb.fNull = FALSE;
a_dcb.fRtsControl = RTS_CONTROL_ENABLE;
a_dcb.fAbortOnError = FALSE;
a_dcb.fDummy2 = 0;
a_dcb.wReserved = 0;
a_dcb.XonLim = 0x100;
a_dcb.XoffLim = 0x100;
a_dcb.ByteSize = 8;
a_dcb.Parity = NOPARITY;
a_dcb.StopBits = ONESTOPBIT;
a_dcb.XonChar = 0x11;
a_dcb.XoffChar = 0x13;
a_dcb.ErrorChar = '?';
a_dcb.EofChar = 0x1A;
a_dcb.EvtChar = 0x10; // Important : caractère déclanchant l'évènement eventCharReceived(
/* Structure récupérant une erreur éventuelle sur le port COM */
a_overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
a_overlap.Internal = 0;
a_overlap.InternalHigh = 0;
a_overlap.Offset = 0;
a_overlap.OffsetHigh = 0;
/* Flag d'ouverture du port */
a_open = false;
}
/******************************************************************************
~QWinSerialPort : Déconstructeur.
Libération de le mémoire
******************************************************************************/
QWinSerialPort::~QWinSerialPort()
{
if(a_open) // Si le port COM est ouvert
{
close(); /* Ferme la connection en cours */
wait(); /* Attend que le processus s'arrête */
}
CloseHandle(a_overlap.hEvent); // Détruit l'évènement erreur sur le port COM
}
/******************************************************************************
close : fermeture du port COM.
******************************************************************************/
void QWinSerialPort::close()
{
/* fermeture du port COM */
a_open = false;
if(CloseHandle(a_hCOM))
a_hCOM = INVALID_HANDLE_VALUE;
return;
}
/******************************************************************************
getDCBConfig : Retourne le baud rate
retour : baudRate
******************************************************************************/
int QWinSerialPort::getBaudRate()
{
return a_dcb.BaudRate;
}
/******************************************************************************
getDCBConfig : Retourne la configuration DCB actuelle du port COM
retour : DCB configuration
******************************************************************************/
DCB QWinSerialPort::getDCBConfig()
{
return a_dcb;
}
/******************************************************************************
getEventChar : Retourne le caractère qui déclanchera le signal
eventCharReceived() lorsqu'il est reçu
retour : le caractère déclancheur d'évènement
******************************************************************************/
char QWinSerialPort::getEventChar()
{
return a_dcb.EvtChar;
}
/******************************************************************************
getReadIntervalTimeout : retourne le temps d'attente de la fonction read
Inutile ici car le port COM est en mode asynchrone
******************************************************************************/
int QWinSerialPort::getReadIntervalTimeout()
{
return a_cto.ReadIntervalTimeout;
}
/******************************************************************************
isOpen : Retourne le statut du port.
retour : vrai si un port COM est ouvert, faux sinon.
******************************************************************************/
bool QWinSerialPort::isOpen()
{
return a_open;
}
/******************************************************************************
open : ouverture et configuration du port COM.
entrée : id : Id du port COM à ouvrir.
retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
bool QWinSerialPort::open(int id)
{
/* variables locales */
char szCOM[16];
/* Si une connexion existe déjà, on la ferme */
if(a_open)
close();
/* construction du nom du port, tentative d'ouverture */
sprintf(szCOM, "COM%d", id);
a_hCOM = CreateFileA(szCOM, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); //FILE_ATTRIBUTE_SYSTEM
if(a_hCOM == INVALID_HANDLE_VALUE)
{
return a_open;
}
/* affectation taille des tampons d'émission et de réception */
SetupComm(a_hCOM, RX_SIZE, TX_SIZE);
/* configuration du port COM */
if(!SetCommTimeouts(a_hCOM, &a_cto) || !SetCommState(a_hCOM, &a_dcb))
{
CloseHandle(a_hCOM);
return a_open;
}
/* on vide les tampons d'émission et de réception, mise à 1 DTR */
PurgeComm(a_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
EscapeCommFunction(a_hCOM, SETDTR);
a_open = true;
start(); /* On active le thread : on met sur écoute le port COM */
return a_open;
}
/******************************************************************************
read : lecture de données reçu du port COM et mis en buffer.
retour : le buffer qui sera remis à 0 aprés l'appel de la fonction
******************************************************************************/
QString QWinSerialPort::read()
{
QString r = a_buffer;
a_buffer.clear();
return r;
}
/******************************************************************************
setEventChar : Configure le baud rate
******************************************************************************/
bool QWinSerialPort::setBaudRate(int baudRate)
{
/* Le débit doit avoir une valeure prédéfinie */
switch(baudRate)
{
case CBR_110:
case CBR_300:
case CBR_600:
case CBR_1200:
case CBR_2400:
case CBR_4800:
case CBR_9600:
case CBR_14400:
case CBR_19200:
case CBR_38400:
case CBR_57600:
case CBR_115200:
case CBR_128000:
case CBR_256000:
break;
default:
return false;
}
a_dcb.BaudRate = baudRate;
if(a_open)
{
return SetCommState(a_hCOM, &a_dcb);
}
return true;
}
/******************************************************************************
setDCBConfig : Importe une configuration DCB pour le port série
******************************************************************************/
bool QWinSerialPort::setDCBConfig(DCB dcb)
{
a_dcb = dcb; //EST CE QUE CEST BON ???? JE NE SAIS PU SI ON PEUT FAIRE CA §§§§§§§§§§§ :s
if(a_open)
{
return SetCommState(a_hCOM, &a_dcb);
}
return true;
}
/******************************************************************************
setEventChar : Configure le caractère qui déclanchera le signal eventCharReceived() lorsqu'il est reçu
******************************************************************************/
bool QWinSerialPort::setEventChar(char c)
{
a_dcb.EvtChar = c;
if(a_open)
{
return SetCommState(a_hCOM, &a_dcb);
}
return true;
}
/******************************************************************************
setReadIntervalTimeout : Configure le temps d'attente de la fonction read
Inutile en mode asynchrone
******************************************************************************/
bool QWinSerialPort::setReadIntervalTimeout(int readIntervalTimeout)
{
a_cto.ReadIntervalTimeout = readIntervalTimeout;
if(a_open)
{
return SetCommTimeouts(a_hCOM, &a_cto);
}
return true;
}
/******************************************************************************
write : écriture d'une chaine sur le port COM.
entrée : s : la chaine à transmettre
retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
bool QWinSerialPort::write(QString s)
{
/* Initialisation du buffer */
char *buffer = NULL;
buffer = (char*)malloc((s.length()+1) * sizeof * buffer);
/* Rempli le buffer */
int i = 0;
QChar *data = s.data();
while (!data->isNull())
{
buffer[i] = data->toAscii();
data++;
i++;
}
buffer[i] = '\0';
/* Transmet le buffer au port COM */
return writeCOM(buffer, i);
}
/******************************************************************************
read : lecture de données sur le port COM.
entrée : buffer : buffer où mettre les données lues.
nBytesToRead : nombre max d'octets à lire.
pBytesRead : variable qui va recevoir le nombre d'octets lus.
retour : vrai si l'opération a réussi, faux sinon.
-------------------------------------------------------------------------------
Remarques : - la constante MAX_WAIT_READ utilisée dans la structure
COMMTIMEOUTS permet de limiter le temps d'attente si aucun
caractères n'est présent dans le tampon d'entrée.
- la fonction peut donc retourner vrai sans avoir lu de données.
******************************************************************************/
bool QWinSerialPort::readCOM(void* buffer, int nBytesToRead)
{
/* Structure évènement erreur sur la lecture */
OVERLAPPED overlapRead;
overlapRead.Internal = 0;
overlapRead.InternalHigh = 0;
overlapRead.Offset = 0;
overlapRead.OffsetHigh = 0;
overlapRead.hEvent = CreateEvent(NULL, true, false, NULL);
/* Lecture du port */
bool result = ReadFile(a_hCOM, buffer, nBytesToRead, NULL, &overlapRead);
ResetEvent(overlapRead.hEvent); // Supression de l'évènement erreur sur la lecture
return result;
}
/******************************************************************************
receiveData : Récupère les données envoyés par le port COM
******************************************************************************/
void QWinSerialPort::receiveData(DWORD event)
{
/* Attention, méthode non testé à fond ...
A débugger si utilisé ! */
QString q;
char buffer[2]; // Récupère un seul caractère
buffer[0] = '\0';
DWORD Errors;
COMSTAT Status;
do
{
if(readCOM(buffer, 1))
{
if(buffer[0] != a_dcb.EvtChar)// | true)
{
buffer[1] = '\0';
a_buffer += QString(buffer);
}
}
ClearCommError(a_hCOM, &Errors, &Status);
}
while(Status.cbInQue > 0); // Est-ce que c'est disposible en mode asynchrone ?
switch(event)
{
case EV_RXCHAR:
emit reading(); // Emission d'un signal de lecture du port COM
break;
case EV_RXFLAG:
emit eventCharReceived(); // Emission du signal indiquant que le caratère spécial à été lu
break;
}
}
/******************************************************************************
run : Active le thread
Met le port COM en mode écoute
******************************************************************************/
void QWinSerialPort::run()
{
/* Récupère les évènement de lecture d'un caractèr et de lecture d'un caractère spécial */
SetCommMask(a_hCOM, EV_RXCHAR | EV_RXFLAG | EV_BREAK);
DWORD event = 0;
/* On attend qu'un événement sur le port COM se produisse */
while(a_open)
{
event = 0;
ResetEvent(a_overlap.hEvent);
if(!WaitCommEvent(a_hCOM, &event, &a_overlap))
{
if (GetLastError() != ERROR_IO_PENDING)
{
//close();
//return;
}
}
if(WaitForSingleObject(a_overlap.hEvent, INFINITE) == WAIT_OBJECT_0)
{
//overlap event occured
DWORD undefined;
if (!GetOverlappedResult(a_hCOM, &a_overlap, &undefined, false))
{
emit error(GetLastError());
//qWarning("Comm event overlapped error %ld", GetLastError());
close();
return;
}
/* Données reçue via le port COM */
if(event & EV_RXCHAR == EV_RXCHAR)
receiveData(EV_RXCHAR);
if((event & EV_RXFLAG) == EV_RXFLAG)
receiveData(EV_RXFLAG);
//if(event & EV_BREAK == EV_BREAK)
//close();
}
}
}
/******************************************************************************
write : envoi de données sur le port COM.
entrée : buffer : buffer avec les données à envoyer.
nBytesToWrite : nombre d'octets à envoyer.
pBytesWritten : variable qui va recevoir le nombre d'octets
envoyés.
retour : toujours vrai (vrai si l'opération a réussi, faux sinon
valable en mode synchrone uniquement)
******************************************************************************/
bool QWinSerialPort::writeCOM(void* buffer, int nBytesToWrite)
{
OVERLAPPED overlapWrite;
overlapWrite.Internal = 0;
overlapWrite.InternalHigh = 0;
overlapWrite.Offset = 0;
overlapWrite.OffsetHigh = 0;
overlapWrite.hEvent = CreateEvent(NULL, true, false, NULL);
/* écriture sur le port */
bool result = WriteFile(a_hCOM, buffer, nBytesToWrite, NULL, &overlapWrite); // Always false because : asynchronous
ResetEvent(overlapWrite.hEvent);
return true;
}