Salut a tous

Je souhaite ecrire des fonctions de communications utilisant un des port COM du PC, aucun soucis pour ouvrir le port, le configurer et le fermer. Pas de soucis non plus pour envoyer des datas, par contre impossible de recevoir (les questions sont en bas du post )

Edit: Je code avec Code::Blocks / OS: Windows XP

le .h

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* Definition des codes d'erreurs port Serie */
typedef enum
{
    _ErrorNone,         // Pas d'erreur
    _ErrorCreate,       // Erreur lors de l'ouverture du port (déja utilisé)
    _ErrorInexistant,   // Port COM n'existe pas
    _ErrorConfigPort,   // Erreur lors de la configuration du PORT
    _ErrorConfigTimeout,// Erreur lors de la configuration des Timeouts
    _ErrorFrameDef,     // Erreur de définition de la trame
    _ErrorTx,           // Erreur lors de l'emission
    _ErrorParamEventRx, // Erreur de parametrage de l'evenement "RX char"
    _ErrorRx,           // Erreur lors de la reception
    _ErrorTimeout,      // Delais depasse pour la reponse progger
 
    _ErrorNack,       // Demande non prise en compte
    _ErrorChecksum    // Erreur de Checksum
}enSerialError;
 
 
/* Definition de la structure de configuration du port serie */
typedef struct SerialParam SerialParam;
struct SerialParam
{
    char ComPort[5];        // Nom du PORT selectionné
    long BaudRate;          // Débit
    long DataBitsNumber;    // Nombre de bits de donnée
};
 
 
enSerialError OpenSerialPort(SerialParam *pSerialConfig);
 
void CloseSerialPort();
 
enSerialError ReadSerialPortOverlapped(char* pcharBuffer, long* plgNbBytesRead, long lgNbBytesToRead);
 
enSerialError WriteSerialPortOverlapped(const char* pcharBuffer, long lgNbBytes);
Je vous colle ici les parties de code du .c

Ouverture/Configuration du port:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/********************************************************************/
/* Ouverture et Initialisation du port COM                          */
/********************************************************************/
/*  - PARAMETRE -                                                   */
/********************************************************************/
/* .Pointeur sur la structure SerialParam                           */
/********************************************************************/
/*  - SORTIE -                                                      */
/********************************************************************/
/* .Code d'erreur                                                   */
/*  ==> _ErrorNone si tout c'est bien passe                         */
/*  ==> _ErrorCreate si impossible d'ouvrir le port                 */
/*  ==> _ErrorConfig si impossible de configurer le port            */
/*  ==> _ErrorTimeout si impossible de configurer les timeouts      */
/********************************************************************/
enSerialError OpenSerialPort(SerialParam *pSerialConfig)
{
    DCB dcbPort;                        // Déclaration d'une structure DCB
    COMMTIMEOUTS ComTimeouts;           // Structure COMMTIMEOUTS
    enSerialError ComError=_ErrorNone;
 
/****************************************************/
/*                  Ouverture Port                  */
/****************************************************/
    hPort=CreateFile(pSerialConfig->ComPort,    // Nom du port ouvert
                GENERIC_READ|GENERIC_WRITE,     // Acces en Lecture/Ecriture
                0,                              // Pas de partage possible du Port une fois ouvert
                NULL,                           // Pas d'heritage
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                NULL);
 
 
/* Test si ouverture a réussi*/
    if(hPort==INVALID_HANDLE_VALUE)
    {
/* erreur lors de la création, port utilise par une autre ressource*/
        ComError=_ErrorCreate;  //
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
/* Le port n'existe pas */
            ComError=_ErrorInexistant;
        }
    }
 
    else
    {
/* On vide les buffers d'entree/sortie */
        PurgeComm(hPort,
                PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
 
/****************************************************/
/*                Parametrage du Port               */
/****************************************************/
        dcbPort.DCBlength=sizeof(DCB);
        GetCommState(hPort,&dcbPort);               // Config Actuelle
 
        dcbPort.BaudRate=pSerialConfig->BaudRate;   // Débit
        dcbPort.fBinary=TRUE;                       // binary mode, no EOF check (obligatoire pour appli windows)
        dcbPort.fParity=FALSE;                      // disable parity checking
        dcbPort.ByteSize=pSerialConfig->DataBitsNumber;// number of bits/byte, 4-8
        dcbPort.Parity=NOPARITY;                    // 0-4=no,odd,even,mark,space
        dcbPort.StopBits=ONESTOPBIT;                // 0,1,2 = 1, 1.5, 2
 
/* Configuration du port en fonction des parametres de la struct DCB */
        if(!SetCommState(hPort,&dcbPort))
        {
            ComError=_ErrorConfigPort;
        }
 
/****************************************************/
/*            Parametrage des Timeouts              */
/****************************************************/
        GetCommTimeouts(hPort,&ComTimeouts);
 
        ComTimeouts.ReadIntervalTimeout=MAXDWORD;   
        ComTimeouts.ReadTotalTimeoutMultiplier=0;   
        ComTimeouts.ReadTotalTimeoutConstant=0;     
        ComTimeouts.WriteTotalTimeoutMultiplier=10; // 10ms de timeout par octet (@1200bds 1 octet=8.33ms)
        ComTimeouts.WriteTotalTimeoutConstant=1000; // 500ms de timeout pour une trame (@1200bds, 1000ms = 120 octets)
 
        if(!SetCommTimeouts(hPort,&ComTimeouts))
        {
            ComError=_ErrorConfigTimeout;
        }
    }
    return ComError;
}
Fermeture
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
/********************************************************************/
/* Fermeture du port COM                                            */
/********************************************************************/
void CloseSerialPort()
{
    if(hPort!=NULL)
    {
        CloseHandle(hPort);
        hPort=NULL;
    }
}
Ecriture
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
enSerialError WriteSerialPortOverlapped(const char* pcharBuffer, long lgNbBytes)
{
    enSerialError ComError=_ErrorNone;  // Pas d'erreur au demarrage
    OVERLAPPED osWrite = {0};
    DWORD dwWritten;
 
    // Create this writes OVERLAPPED structure hEvent.
    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osWrite.hEvent == NULL)
    {
        printf("// Error creating overlapped event handle.");
        ComError=_ErrorTx;
        CloseSerialPort();
    }
    else
    {
        // Issue write.
        if (!WriteFile(hPort,pcharBuffer,lgNbBytes,&dwWritten,&osWrite))
        {
            if (GetLastError()!=ERROR_IO_PENDING)
            {
                // WriteFile failed, but it isn't delayed. Report error and abort.
                ComError=_ErrorTx;
                CloseSerialPort();
            }
            else
            {
                // Write is pending.
                if (!GetOverlappedResult(hPort, &osWrite, &dwWritten, TRUE))
                {
                    ComError=_ErrorTx;
                    CloseSerialPort();
                }
                else
                    // Write operation completed successfully.
                    ComError=_ErrorNone;
            }
        }
        else
            // WriteFile completed immediately.
            ComError=_ErrorNone;
    }
   CloseHandle(osWrite.hEvent);
   return ComError;
 
}
Lecture
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
enSerialError ReadSerialPortOverlapped(char* pcharBuffer, long* plgNbBytesRead, long lgNbBytesToRead)
{
    DWORD dwRes;
    BOOL fWaitingOnRead = FALSE;
    OVERLAPPED osReader = {0};
    enSerialError ComError=_ErrorNone;  // Pas d'erreur au demarrage
 
    // Create the overlapped event. Must be closed before exiting
    // to avoid a handle leak.
    osReader.hEvent=CreateEvent(NULL,   // Handle cannot be inherited by child
                                TRUE,   // Create a Manual Reset
                                FALSE,  // Event Initial state = "non signaled"
                                NULL);  // Event object has no name
 
    if (osReader.hEvent == NULL)
    {
        printf("// Error creating overlapped event; abort.");
        return _ErrorRx;
    }
    if (!fWaitingOnRead)
    {
        // Issue read operation.
        if(!ReadFile(hPort,pcharBuffer,lgNbBytesToRead,plgNbBytesRead,&osReader))
        {   // If ReadFile return FALSE:
            if(GetLastError()!=ERROR_IO_PENDING)
            {    // read not delayed by OS?
                ComError=_ErrorRx;      // Error in communications; report it.
                CloseSerialPort();
            }
            else
                fWaitingOnRead = TRUE;
        }
        else // ReadFile return TRUE
        {
            // read completed immediately
            //HandleASuccessfulRead(pcharBuffer,*plgNbBytesRead); // fonction a ecrire
            ComError=_ErrorNone;
        }
    }
    if (fWaitingOnRead)
    {
        dwRes=WaitForSingleObject(osReader.hEvent,READ_TIMEOUT);
        switch(dwRes)
        {
            /* Read completed. */
            case WAIT_OBJECT_0:
                if(!GetOverlappedResult(hPort,&osReader,plgNbBytesRead,FALSE))
                {   // Error in communications; report it.
                    ComError=_ErrorRx;
                    CloseSerialPort();
                }
                else
                    // Read completed successfully.
                    //HandleASuccessfulRead(pcharBuffer,*plgNbBytesRead); // fonction a ecrire
                    ComError=_ErrorNone;
 
                //  Reset flag so that another operation can be issued.
                fWaitingOnRead=FALSE;
                break;
 
            /* Read not completed, Timeout occured. */
            case WAIT_TIMEOUT:
                // Operation isn't complete yet. fWaitingOnRead flag isn't
                // changed since I'll loop back around, and I don't want
                // to issue another read until the first one finishes.
                ComError=_ErrorTimeout;
                CloseSerialPort();
                fWaitingOnRead=FALSE;
                break;
 
            default:
                // Error in the WaitForSingleObject; abort.
                // This indicates a problem with the OVERLAPPED structure's
                // event handle.
                ComError=_ErrorRx;
                CloseSerialPort();
                fWaitingOnRead=FALSE;
                break;
        }
    }
    CloseHandle(osReader.hEvent);
    return ComError;
}
Donc j'ai créé 2 ports virtuels connectés l'un a l'autre pour tester la communication entre mon soft et un autre de type hyperterminal. Je recois donc bien sur le terminal les trames envoyées par mon soft, par contre aucune data envoyée par le terminal n'est recue par mon soft, pourtant je resors de ma fonction Read sans code d'erreur.

J'ai donc testé en debug pour voir ce qui se passe, donc lorsque je rentre dans la fonction Read le flag "fWaitingOnRead" est a FALSE, on rentre donc dans le IF pour executer "ReadFile(hPort,pcharBuffer,lgNbBytesToRead,plgNbBytesRead,&osReader)", cette fonction renvoie toujours TRUE, que je simule l'envoi d'une trame ou non depuis l'hyperterminal avant de passer sur ReadFile. Et c'est la le probleme, lorsque je lis l'aide MSDN (ICI) il est marqué qu'en mode Overlapped, la fonction Read renvoie FALSE, ce qui permet alors de passer dans la seconde partie et de tester si oui ou non la trame a été recue avant la fin du Timeout parametré par "READ_TIMEOUT" (GetOverlappedResult(hPort,&osReader,plgNbBytesRead,FALSE)).

J'ai besoin d'utiliser ce timeout, car dans un premier temps j'avais mis en place un mode "non overlapped" qui fonctionne bien pour lecture/ecriture, sauf dans le cas ou la cible ne repondait pas (cible HS ou OFF, etc...), ce qui bloquait completement l'execution de mon programme (attente d'un octet indefiniment sur le port COM).

Depuis le debut de la semaine j'essaie en vain d'ecrire des fonctions d'ecriture/lecture operationnelles a 100%, je m'en remets donc a vous

Merci d'avance pour votre aide et conseils