Signal RTS et port COM...

Signaler
Messages postés
93
Date d'inscription
mardi 3 juin 2003
Statut
Membre
Dernière intervention
26 septembre 2006
-
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
-
Bonjour à tous,

je communique avec un dispositif électronique via un port COM du PC. J'aimerai mettre le signal RTS à 1 avant d'envoyer ma trame, et le remettre à 0 quand tous les caractéres sont effectivement partis du port. Voici un extrait de mon code :

DWORD dwEvtMask;
char *bufferS = "toto";

// ouverture du port nomPort
hPort = CreateFile
( "COM1", GENERIC_WRITE|GENERIC_READ,0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, );

// mise en place du mask d'événement ==> dernier caractére envoyé (????)
SetCommMask(hPort, EV_TXEMPTY)

// création de l'événement qui signalera la fin de l'envoi; RAZ manuel; non signalé au départ
overloppedAttEnvoi.hEvent = CreateEvent(NULL, true, 0, NULL);
overloppedAttEnvoi.Internal = 0;
overloppedAttEnvoi.InternalHigh = 0;
overloppedAttEnvoi.Offset = 0;
overloppedAttEnvoi.OffsetHigh = 0;

// création de l'événement qui signalera la fin de l'écriture; RAZ auto; non signalé au départ
overloppedEcri.hEvent = CreateEvent(NULL, false, 0, NULL);
overloppedEcri.Internal = 0;
overloppedEcri.InternalHigh = 0;
overloppedEcri.Offset = 0;
overloppedEcri.OffsetHigh = 0;

/* mise à 1 de RTS */
EscapeCommFunction(hPort,SETRTS)

// écrit
WriteFile(hPort, bufferS, nbCharAEcrire, &nbCharEcrit, &overloppedEcri)

// attend la fin de l'envoi
WaitCommEvent(hPort, &dwEvtMask, &overloppedAttEnvoi)
iLastErr = GetLastError();
if (iLastErr != ERROR_IO_PENDING)
printf ("Probleme à l'envoi! %i\n",iLastErr);
else
{
// l'envoi est en cours ==> attend la fin
rap = WaitForSingleObject(overloppedAttEnvoi.hEvent, 1000);
switch (rap)
{
case WAIT_OBJECT_0:
// fin de l'écriture, test
if (!GetOverlappedResult(hPort, &overloppedAttEnvoi, &nbCharEcrit, false))
{
iLastErr = GetLastError();
if (iLastErr == ERROR_IO_INCOMPLETE)
printf("%s %d","Operation d'envoi incompléte",iLastErr);
else
printf ("Erreur pendant l'envoi : %x et rap : %d\n" , GetLastError(),rap);
}
else
{
// fin de l'envoi
ResetEvent(overloppedAttEnvoi.hEvent);
EscapeCommFunction(hPort,CLRRTS) // met à 0 RTS
}break;
default:
printf ("Erreur pendant l'envoi : %x et rap : %d\n" , GetLastError(),rap);
}
}

Normalement je remet à 0 RTS quand le dernier caractère est parti, mais NON!
RTS redescend en plein milieu de ma trame!!!

Je n'arrive pas à voir ce qui se passe, alors si quelqu'un a une idée je prend.

Merci.
Lamalice83Sans MS ;)

6 réponses

Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
voici une boucle qui attend que les données soit envoyées avec OVERLAPPED :

DWORD dwNbBytesWritten;
OVERLAPPED ov;
ZeroMemory(&ov, sizeof(OVERLAPPED));
if(!Write(hCom, lpBuffer, dwNbBytesToWrite, &dwNbBytesWritten, &ov))
{
// si erreur autre que envoi non terminé
if(GetLastError() != ERROR_IO_PENDING)
return 0;

// on attend que l'envoi soit fini
while(!GetOverlappedResult(hCom, &ov, &dwNbBytesWritten, TRUE))
{
if(GetLastError() != ERROR_IO_INCOMPLETE)
break;
}
}


Le plus simple c'est quand meme de se passer du flag OVERLAPPED et dans ce cas WriteFile et ReadFile ne retournent pas tant que les octets n'ont pas été lus /écrit.
Messages postés
93
Date d'inscription
mardi 3 juin 2003
Statut
Membre
Dernière intervention
26 septembre 2006

La méthode que tu préconises est la méthode synchrone, mais même avec celle là c'est pareille.

Ta boucle while et mon WaitForSingleObject(overloppedAttEnvoi.hEvent, 1000) font la même chose : elles se 'débloquent' quand l'événement de OVERLAPPED est signalé.

Je ne comprend pas se qui se passe..... HEEEEEEELPPPP

Lamalice83Sans MS ;)
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
Et la méthode sans le FILE_FLAG_OVERLAPPED donne ce même résultat ?

c'est à dire :

char *bufferS = "toto";

// ouverture du port nomPort
hPort = CreateFile
( "COM1", GENERIC_WRITE|GENERIC_READ,0, NULL, OPEN_EXISTING, 0,NULL );

/* mise à 1 de RTS */
EscapeCommFunction(hPort,SETRTS)

// écrit
WriteFile(hPort, bufferS, nbCharAEcrire, &nbCharEcrit, NULL)

EscapeCommFunction(hPort,CLRRTS) // met à 0 RTS

si marche pas, il doit falloir faire un WaitCommEvent après (je doit pouvoir trouver un exemple qq part)
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
Exemple avec WaitCommEvent (non testé pour le RTS)

// ouverture
HANDLE hCOM = CreateFile("COM1", GENERIC_READ|GENERIC_WRITE, 0, NULL, FILE_ATTRIBUTE_SYSTEM, FILE_FLAG_OVERLAPPED, NULL);

// event à surveiller
SetCommMask(hCOM, EV_TXEMPTY);

// RTS=1
EscapeCommFunction(hCOM, SETRTS);

// écriture
OVERLAPPED ovWrite = {0};
DWORD dwBytesWritten;
WriteFile(hCOM, "SALUT", 5, &dwBytesWritten, NULL);

// attente fin de l'envoi
OVERLAPPED ovWait = {0};
ovWait.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD dwEvtMask;
if(!WaitCommEvent(hCOM, &dwEvtMask, &ovWait))
{
// si toujours en attente
if(GetLastError() == ERROR_IO_PENDING)
{
// on attent que l'opération se termine ou qu'elle soit interrompue
DWORD dwResult;
while(!GetOverlappedResult(hCOM, &ovWait, &dwResult, TRUE))
{
if(GetLastError() != ERROR_IO_INCOMPLETE)
break;
}
}
}
CloseHandle(ovWait.hEvent);

// RTS=0
EscapeCommFunction(hCOM, CLRRTS);

// fermeture
CloseHandle(hCOM);
Messages postés
93
Date d'inscription
mardi 3 juin 2003
Statut
Membre
Dernière intervention
26 septembre 2006

C'est quasiment la même chose que j'ai fait mais ça ne marche pas.
On m'a donné la solution : L'aide MSDN dit : EV_TXEMPTY signale que le dernier caractère est parti, ce qui est FAUX! Il signal qu'on ne peut plus mettre de caractère dans le buffer de sortie.
La seule solution est d'aller directement lire les registres sur le composant lui même : l'octet à l'adresse 0x03fd pour le port COM1.

Mais je sais comment récupérer ou lire cet octet?????

Lamalice83
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
il ya encore la fonction FlushFileBuffers

pour accès direct au hardware :

sous Win9x/ME, tu peut faire :
#include <conio.h>
BYTE b = _inp(0x3FD);

pour Win2k/NT/XP tu n'as pas accès au ports directement et là faut passer par un driver ou une dll spéciale.

ici un exemple ave le por parallèle pour accès direct au harware :
http://www.cppfrance.com/code.aspx?ID=21060