Signal RTS et port COM...

cs_lamalice83 Messages postés 93 Date d'inscription mardi 3 juin 2003 Statut Membre Dernière intervention 26 septembre 2006 - 14 oct. 2004 à 09:22
ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 - 15 oct. 2004 à 11:35
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

ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 7
14 oct. 2004 à 11:40
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.
0
cs_lamalice83 Messages postés 93 Date d'inscription mardi 3 juin 2003 Statut Membre Dernière intervention 26 septembre 2006
14 oct. 2004 à 13:24
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 ;)
0
ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 7
14 oct. 2004 à 19:47
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)
0
ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 7
14 oct. 2004 à 20:18
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);
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_lamalice83 Messages postés 93 Date d'inscription mardi 3 juin 2003 Statut Membre Dernière intervention 26 septembre 2006
15 oct. 2004 à 08:39
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
0
ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 7
15 oct. 2004 à 11:35
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
0
Rejoignez-nous