IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Probleme communication sur port COM (Overlapped I/O)


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut Probleme communication sur port COM (Overlapped I/O)
    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

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 69
    Points
    69
    Par défaut
    Quand j'utilise le port série, je l'ouvre avec des options en plus, c'est peut-être une piste pour toi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    HANDLE hFile = CreateFile("COM1",	GENERIC_READ|GENERIC_WRITE,
    			FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
    			FILE_ATTRIBUTE_NORMAL,NULL);

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 69
    Points
    69
    Par défaut
    Bon je balance tout, ici, il s'agit de lire à la volée des données du port série suite à une demande. Code testé et qui fonctionne depuis 5 ans sans problème.
    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
     
    HANDLE CRescueConceptDlg::OpenCommPort()
    {
    	HANDLE hFile = CreateFile("COM1",	GENERIC_READ|GENERIC_WRITE,
    		FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
    		FILE_ATTRIBUTE_NORMAL,NULL);
    	if ( !hFile ){
    		CString sError=cPort;
    		sError+=" impossible à ouvrir";
    		AfxMessageBox(sError);
    	}
    	else{
    	// Buffers.
    		SetupComm(hFile,255,255);
     
    		// Parametres.( Idem commande MODE )
    		DCB dcb;
    		memset( &dcb, 0, sizeof( dcb ) );
    		dcb.DCBlength = sizeof( dcb );
    		BuildCommDCB( "baud=57600 parity=N data=8 stop=1", &dcb );
    		SetCommState( hFile, &dcb );
     
    		// Time out
    		COMMTIMEOUTS CommTimeouts;
    		memset( &CommTimeouts, 0, sizeof(CommTimeouts));
    		CommTimeouts.ReadIntervalTimeout = 1000; 
    		CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
    		CommTimeouts.ReadTotalTimeoutConstant = 4000;
    		CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
    		CommTimeouts.WriteTotalTimeoutConstant = 2000;
    		SetCommTimeouts(hFile,&CommTimeouts);
    	}
    	return hFile;
    }
     
    bool sendAndReceiveData()
      HANDLE hFile;
      if(hFile=OpenCommPort()){
     
    	unsigned long	nbWr;
            // envoie la commande de lecture
    	WriteFile(hFile,"CRmmm",5,&nbWr,NULL);
            // attend les données
    	unsigned char cBuff[2048];
    	unsigned long nbRd;
    	int i=0;
    	do{
    		ReadFile(hFile,cBuff+i,1,&nbRd,NULL);
    		i++;
    	}while((i<0x800)&&(nbRd!=0));
     
            traiteRxData(cBuff);
     
    	CloseCommPort(hFile);
        }
    }

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Merci Daffy pour ta participation. J'ai réussi entre temps a faire fonctionner les Timeouts de la structure COMMTIMEOUTS, mais je vais m'inspirer de ton code pour rendre le mien plus propre

    Cependant ces solutions sont valables uniquement pour des ports ouverts en "Non overlapped", et je n'arrive toujours pas à comprendre pourquoi en "Overlapped" ca ne fonctionne pas.

    Je vais continuer a developper mon appli avec une fonction de reception semblable a la tienne, je reviendrais plus tard sur le mode Overlapped sauf si qq un arrive a me donner un coup de main avant

    Encore merci

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Personne n'a mis en place de comm serie en C ?

Discussions similaires

  1. Communication avec modem GSM sur port COM
    Par cheasy dans le forum Langage
    Réponses: 16
    Dernier message: 05/06/2013, 10h32
  2. [Débutant] Communication sur port com
    Par alinokk dans le forum C#
    Réponses: 0
    Dernier message: 08/05/2012, 13h42
  3. Probleme communication bluetooth sur port Com
    Par Folkene dans le forum C++
    Réponses: 0
    Dernier message: 30/05/2009, 18h45
  4. Probleme de communication sur port serie
    Par campistrol dans le forum Matériel
    Réponses: 4
    Dernier message: 30/01/2008, 15h27
  5. Problème de reception sur Port COM
    Par Revan777 dans le forum C
    Réponses: 9
    Dernier message: 19/04/2005, 21h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo