Envoi sur port série

alilou2955 Messages postés 8 Date d'inscription mercredi 9 juin 2010 Statut Membre Dernière intervention 4 avril 2012 - 15 nov. 2010 à 00:49
cs_atlantic44 Messages postés 1 Date d'inscription lundi 4 septembre 2006 Statut Membre Dernière intervention 22 novembre 2010 - 22 nov. 2010 à 17:03
Bonjour.
J'ai modifié un pgme C dispo sur le net pour l'adapter à mes besoins.
Bref, ce programme C est sensé envoyer des données qu'il récupère du fichier BehavSimul.txt.
Le programme semble faire ce qui lui est demandé, mais quand j'ai créé un autre programme qui écoute ce qui est envoyé sur ce port, je me suis rendu compte que parfois il envoie la chaine1 et la moitié de la chaine 2 à la fois, parfois juste la moitié d'une chaine. Si vous comprenez où est le problème, je vous remercie de me l'indiquer.
Voici le contenu du programme SendDataToSerialPort.c
[code=cpp]
/******************************************************************************
SendDataToSerialPort.c
Ce petit soft permet de lire le contenu du fichier BehavSimul.txt formé de
plusieurs lignes. Chaque ligne a la forme suivante "DETEX00x y", où x
correspond au numéro du capteur qui a détecté le mouvement du patient et y le
temps passé par le patient dans la zone couverte par le capteur x.

Ce soft envoie donc sur le port COMz (z à lire via le clavier) la commande
DETEX00x, puis attend y secondes avant de reboucler pour lire la prochaine ligne
....

******************************************************************************/

#include
#include
#include
#include
//#include

/*=============================================================================
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) */


/*=============================================================================
Variables globales.
=============================================================================*/

/* Handle du port COM ouvert */
HANDLE g_hCOM = NULL;

/* Délais d'attente sur le port COM */
COMMTIMEOUTS g_cto =
{
MAX_WAIT_READ, /* ReadIntervalTimeOut */
0, /* ReadTotalTimeOutMultiplier */
MAX_WAIT_READ, /* ReadTotalTimeOutConstant */
0, /* WriteTotalTimeOutMultiplier */
0 /* WriteTotalTimeOutConstant */
};

/* Configuration du port COM */
DCB g_dcb =
{
sizeof(DCB), /* DCBlength */
19200, /* BaudRate */ //J'ai mis 19200 au lieu de 9600,
TRUE, /* fBinary */
FALSE, /* fParity */
FALSE, /* fOutxCtsFlow */
FALSE, /* fOutxDsrFlow */
DTR_CONTROL_DISABLE, /* fDtrControl */
FALSE, /* fDsrSensitivity */
FALSE, /* fTXContinueOnXoff */
FALSE, /* fOutX */
FALSE, /* fInX */
FALSE, /* fErrorChar */
FALSE, /* fNull */
RTS_CONTROL_ENABLE, /* fRtsControl */
FALSE, /* fAbortOnError */
0, /* fDummy2 */
0, /* wReserved */
0x100, /* XonLim */
0x100, /* XoffLim */
8, /* ByteSize */
NOPARITY, /* Parity */
ONESTOPBIT, /* StopBits */
0x11, /* XonChar */
0x13, /* XoffChar */
'?', /* ErrorChar */
0x1A, /* EofChar */
0x10 /* EvtChar */
};

/*=============================================================================
Fonctions du module.
=============================================================================*/
BOOL OpenCOM (int nId);
BOOL CloseCOM ();
BOOL ReadCOM (void* buffer, DWORD nBytesToRead, LPDWORD pBytesRead);
BOOL WriteCOM (void* buffer, DWORD nBytesToWrite, LPDWORD pBytesWritten);

/******************************************************************************
main : point d'entrée du programme.
******************************************************************************/
int main(void)
{
/* variables locales */
char buffer[256];
int nId, nChoice;//, nBytesWritten, nBytesRead;
//int* pByteRead, pByteWritten;
DWORD nBytesWritten, nBytesRead;

/* demande du numéro du port COM */
// On boucle tant que le numéro de port est le bon
int GoodCOM=0;
while (!GoodCOM)
{
printf("\nEntrez le numero du port COM : ");
scanf("%d", &nId);
/* tentative d'ouverture */
printf("Ouverture et configuration du port COM%d...\r\n", nId);
if(!OpenCOM(nId)) {printf ("\nImpossible d'ouvrir le port COM%d. Soit il est occupe', soit il n'existe pas.\n (CTRL-C pour quitter)\n",nId);} //system ("PAUSE") ; return -1;}
else {GoodCOM=1; printf("...OK, port COM%d ouvert\r\n",nId);}
}
//CloseCOM();

/* Envoyer les données sur le port ComX. Boucle jusqu'à fin du fichier*/
// Ouvrir le fichier qui contient le circuit parcouru par le patient (simulation) : BehavSimul.txt
FILE *f=NULL;
int tps_Transition;
char position[]="DETX001";
char *nomfichier="BehavSimul.txt";
f=fopen(nomfichier,"r" );
if (f==NULL) {printf ("\nImpossible d'ouvrir le fichier %s. Peut-être ce nom est incorrect.\n", nomfichier); exit(1);}
else printf ("Fichier %s ouvert\n",nomfichier);

while (fscanf(f,"%s %d",position,&tps_Transition)!=EOF){
printf("\nCommande enregistre'e: %s. Temps passe' dans cette zone: %d secondes.\n",position,tps_Transition);
//OpenCOM(nId);
if(WriteCOM(position,strlen(position), &nBytesWritten)) //Pour enlever doute, je mets parfois des valeurs fixes 7, 8... au lieu de strlen(position)
printf("%d octet(s) envoye(s).\r\n", (int)nBytesWritten);
else
printf("Erreur lors de l'envoi.\r\n");
printf ("La commande \"%s\" est envoye'e sur le port COM%d.\n",position,nId);

printf ("Attente de %d secondes avant envoi de la prochaine commande.\n",tps_Transition);
SDL_Delay(1000*tps_Transition);
PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
} //fin du while
fclose (f); // Fermeture du fichier ouvert
CloseCOM(); /* fermeture du port COM et retour */

system("PAUSE"); //Faire une pause (arret) avant de quitter la fenetre DOS
return 0;
} // fin de main


/******************************************************************************
OpenCOM : ouverture et configuration du port COM.
entrée : nId : Id du port COM à ouvrir.
retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL OpenCOM(int nId)
{
/* variables locales */
char szCOM[16];

/* construction du nom du port, tentative d'ouverture */
sprintf(szCOM, "COM%d", nId);
g_hCOM = CreateFile(szCOM, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
if(g_hCOM == INVALID_HANDLE_VALUE)
{
printf("Erreur lors de l'ouverture du port COM%d", nId);
return FALSE;
}

/* affectation taille des tampons d'émission et de réception */
SetupComm(g_hCOM, RX_SIZE, TX_SIZE);

/* configuration du port COM */
if(!SetCommTimeouts(g_hCOM, &g_cto) || !SetCommState(g_hCOM, &g_dcb))
{
printf("Erreur lors de la configuration du port COM%d", nId);
CloseHandle(g_hCOM);
return FALSE;
}

/* on vide les tampons d'émission et de réception, mise à 1 DTR */
PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
//Commenté, car DTR désactivé
//EscapeCommFunction(g_hCOM, SETDTR);
return TRUE;
} //Fin fct OpenCOM()

/******************************************************************************
CloseCOM : fermeture du port COM.
retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL CloseCOM()
{
/* fermeture du port COM */
CloseHandle(g_hCOM);
return TRUE;
} // Fin fct CloseCOM()

/******************************************************************************
ReadCOM : 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 ReadCOM(void* buffer, DWORD nBytesToRead, LPDWORD pBytesRead)
{
return ReadFile(g_hCOM, buffer, nBytesToRead, pBytesRead, NULL);
}

/******************************************************************************
WriteCOM : 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 : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL WriteCOM(void* buffer, DWORD nBytesToWrite, LPDWORD pBytesWritten)
{
/* écriture sur le port */
return WriteFile(g_hCOM, buffer, nBytesToWrite, pBytesWritten, NULL);
}
/code

Voici le contenu du fichier BehavSimul.txt:
[code=autre]
DETX001 2
DETX002 5
DETX008 2
DETX009 6
DETX008 2
DETX009 3
DETX008 3
DETX002 2
DETX001 4
/code

Voici les résultats des tests que j'ai effectués:
Résultat de l'exécution du programme SendDataToSerialPort.exe :
[code=autre]
Entrez le numero du port COM : 1
Ouverture et configuration du port COM1...
...OK, port COM1 ouvert
Fichier BehavSimul.txt ouvert

Commande enregistre'e: DETX001. Temps passe' dans cette zone: 2 secondes.
7 octet(s) envoye(s).
La commande "DETX001" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX002. Temps passe' dans cette zone: 5 secondes.
7 octet(s) envoye(s).
La commande "DETX002" est envoye'e sur le port COM1.
Attente de 5 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX008. Temps passe' dans cette zone: 2 secondes.
7 octet(s) envoye(s).
La commande "DETX008" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX009. Temps passe' dans cette zone: 6 secondes.
7 octet(s) envoye(s).
La commande "DETX009" est envoye'e sur le port COM1.
Attente de 6 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX008. Temps passe' dans cette zone: 2 secondes.
7 octet(s) envoye(s).
La commande "DETX008" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX009. Temps passe' dans cette zone: 3 secondes.
7 octet(s) envoye(s).
La commande "DETX009" est envoye'e sur le port COM1.
Attente de 3 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX008. Temps passe' dans cette zone: 3 secondes.
7 octet(s) envoye(s).
La commande "DETX008" est envoye'e sur le port COM1.
Attente de 3 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX002. Temps passe' dans cette zone: 2 secondes.
7 octet(s) envoye(s).
La commande "DETX002" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX001. Temps passe' dans cette zone: 4 secondes.
7 octet(s) envoye(s).
La commande "DETX001" est envoye'e sur le port COM1.
Attente de 4 secondes avant envoi de la prochaine commande.
..
Appuyez sur une touche pour continuer...
/code
Voici ce que j'ai capturé sur le port COM2 (COM1 et COM2 sont virtuels !!!), suite à l'exécution du programme SendDataToSerialPort.exe:
[code=autre]
Entrez le numero du port a ecouter COM : 2
Ouverture et configuration du port COM2...
...OK, port COM2 ouvert
7 octet(s) recu(s) :DETX001
7 octet(s) recu(s) :DETX002
14 octet(s) recu(s) :DETX008DETX009
7 octet(s) recu(s) :DETX008
14 octet(s) recu(s) :DETX009DETX008
14 octet(s) recu(s) :DETX002DETX001
/code

J'ai fait un autre test où j'ai modifié le prgme comme suit: J'ai mis "if(WriteCOM(position,8, &nBytesWritten))" (ie. à la place de strlen(position) j'ai mis la valeur 8)

[code=autre]
Entrez le numero du port COM : 1
Ouverture et configuration du port COM1...
...OK, port COM1 ouvert
Fichier BehavSimul.txt ouvert

Commande enregistre'e: DETX001. Temps passe' dans cette zone: 2 secondes.
8 octet(s) envoye(s).
La commande "DETX001" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX002. Temps passe' dans cette zone: 5 secondes.
8 octet(s) envoye(s).
La commande "DETX002" est envoye'e sur le port COM1.
Attente de 5 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX008. Temps passe' dans cette zone: 2 secondes.
8 octet(s) envoye(s).
La commande "DETX008" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX009. Temps passe' dans cette zone: 6 secondes.
8 octet(s) envoye(s).
La commande "DETX009" est envoye'e sur le port COM1.
Attente de 6 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX008. Temps passe' dans cette zone: 2 secondes.
8 octet(s) envoye(s).
La commande "DETX008" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX009. Temps passe' dans cette zone: 3 secondes.
8 octet(s) envoye(s).
La commande "DETX009" est envoye'e sur le port COM1.
Attente de 3 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX008. Temps passe' dans cette zone: 3 secondes.
8 octet(s) envoye(s).
La commande "DETX008" est envoye'e sur le port COM1.
Attente de 3 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX002. Temps passe' dans cette zone: 2 secondes.
8 octet(s) envoye(s).
La commande "DETX002" est envoye'e sur le port COM1.
Attente de 2 secondes avant envoi de la prochaine commande.

Commande enregistre'e: DETX001. Temps passe' dans cette zone: 4 secondes.
8 octet(s) envoye(s).
La commande "DETX001" est envoye'e sur le port COM1.
Attente de 4 secondes avant envoi de la prochaine commande.
..
Appuyez sur une touche pour continuer...
/code

Voici ce que j'ai capturé sur le port COM2 suite à l'exécution du programme SendDataToSerialPort.exe:
[code=autre]
Entrez le numero du port COM : 2
Ouverture et configuration du port COM2...
...OK
Debut de reception de donnees sur COM2
DETX001DETX002DETX008ETX009DETX008ETX009TX008X002001
/code
==> Il me manque les retour à la ligne de cette dernière ligne, mais on remarque déjà sur cette ligne que les messages envoyés ("DETX001" ou "DETX002"...) ne sont pas reçus entièrement; ils sont coupés.
Cette chaine de caractère est envoyée telle qu'elle mais parfois elle est reçue tronquée.

1 réponse

cs_atlantic44 Messages postés 1 Date d'inscription lundi 4 septembre 2006 Statut Membre Dernière intervention 22 novembre 2010
22 nov. 2010 à 17:03
Le cable utilisé est-il complet (TD, RD, RTS, CTS, DCD, DTR) ? ou seulement TD et RD
En général cela vient du fait que le flux de données n'est pas géré (protocole "attrape si tu peux")! Il faut un protocole de gestion des flux matériel (RTS-CTS ) ou logiciel XON-XOFF sinon problème avec les tampons!

L'informatique à la folie!
0
Rejoignez-nous