Communication avec un port COM

Communication avec un port COM - C++ - Programmation

Marsh Posté le 06-04-2004 à 09:00:42    

Salut a tous !
 
Je suis actuellement en train de developper une application pour dialoguer avec un port COM sous Windows2000 avec C++Builder
Mon probleme est que lors de l'ouverture de ce port avec la fonction CreateFile(...), j'ai une erreur comme quoi l'acces au port est refuse.
 
j'ai mon HANDLE definit comme ca :  
hPort = CreateFile ("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
 
et je test immediatement apres de la facon suivante :
if (hPort == INVALID_HANDLE_VALUE)  
ce test vaut vrai a chaque fois
 
si qqn pouvait m'eclairer...
merci d'avance
a+


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 06-04-2004 à 09:00:42   

Reply

Marsh Posté le 06-04-2004 à 09:17:51    

une simple application ne peut accéder directement au matériel sous Windows NT/2000/XP, tu dois faire un driver (accessoirement, une petite recherche sur le forum te montrera que le sujet a déjà été traité maintes fois)


---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)
Reply

Marsh Posté le 06-04-2004 à 09:26:19    

sisi justememt, des fonctions comme outp valides sous 98 par exemple ne fonctionnent plus sous NT, c'est pour cela qu'on doit utiliser un CreateFile.
j'ai vu cette utilisation apres bcp de recherches, a commencer par microsoft...
de plus des gens dans la boite ont deja procede de cette facon
 
donc je sais pas... :/


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 06-04-2004 à 10:55:48    

Tu as fais un GetLastError() pour cibler le problème ?


Message édité par pedro-2480 le 06-04-2004 à 10:56:39

---------------
- Pierre Baudelet -
Reply

Marsh Posté le 06-04-2004 à 12:06:48    

oui ca donnait l'erreur 5 "access denied"
mais en desinstallant le port COM et en redemarrant les pb ont disparu... mnt ca va :p
le nouveau pb c'est que le ReadFile ecrit pas dans mon buffer...  
ahlala la prog windows... :)


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 07-04-2004 à 10:37:24    

*up*
 
j'ai un nouveau probleme au niveau du ReadFile cette fois
en fait le truc c'est que quand je fais une ReadFile il faut que des donnees aient ete envoyees avant (avec un WriteFile), sinon le programme plante carrement, sans aucun message d'erreur
un peu comme qd on essaye de lire dans un fichier : qd on arrive a la fin, ca plante si on gere pas le cas d'erreur
sauf que la, j'arrive pas a le gerer le cas d'erreur...
 
je poursuis mes recherches, mais ca m'arrangerait bien si quelqu'un avait une solution miracle :p


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 07-04-2004 à 13:27:11    

Une piste peut être le fait que tu as positionné le flag overlapped...donc tes opérations de lecture/ecriture sont asynchrones. Ainsi, ReadFile() te rend la main alors que la lecture n'est pas terminée...
 
Pour remédier à cela:
 
Récupérer la valeur de retour de ReadFile(), la traduire avec GetLastError() (attention une valeur de retour non-nulle ne veut pas dire qu'il y a succès, tu dois tester le nombre d'octets effectivement lus):
 
- Retour = ERROR_IO_PENDING: l'opération est en cours...
 
Dans ce cas, le mieux est d'attendre que l'opération se termine, une manière propre consisterait à te servir du Event que tu as passé en paramètre (dans la strucutre overlapped) au ReadFile():
Ex: WaitForSingleObject()...quand cette fonction te rend la main, c'est que:
- les données sont arrivées avant le timeout que tu as défini,
- le timeout a expiré...
 
- Retour = ERROR_HANDLE_EOF: pas de données lues (pb) -> a gérer...
 
A toi de faire le reste ! ;)


---------------
- Pierre Baudelet -
Reply

Marsh Posté le 07-04-2004 à 16:56:03    

ok merci bien ca m'a un peu inspire et je me suis debrouille
j'avais aussi un probleme de pointeur, qui faisait lire des trucs qu'il fallait pas :p
 
maintenant ca va y'a plus de problemes :)
 
merci et puis peut etre a bientot pour de nouveaux soucis ;)


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 13-04-2004 à 12:09:50    

me revoila !!! :p
bon cette fois j'ai un soucis un peu plus grave
en fait, les donnes sont transmises octet par octet sur le port COM, mais apparement, le bit de poids fort ne passe pas. Du coup, c'est comme si il valait toujours 0, ce qui est embettant pour les valeurs negatives par exemple.
 
voila, je cherche des experts en transmission de donnees sur le port serie (c'est ptet pu le bon forum du coup...) parce que la je comprends vraiment pas ce aui se passe  :pt1cable:


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 13-04-2004 à 12:20:07    

t'est bien en 8 bits sans parité ?

Reply

Marsh Posté le 13-04-2004 à 12:20:07   

Reply

Marsh Posté le 13-04-2004 à 12:30:04    

oui oui... 8 bit et aucune parite... :/


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 13-04-2004 à 12:37:55    

Peux-tu poster ton bout de code qui fait l'init et qui formate / envoit les datas ?

Reply

Marsh Posté le 13-04-2004 à 12:46:33    

Même si c'est pas propre, ceci fonctionne très bien:
 

Code :
  1. class WinSerial {
  2. private:
  3.    int NumPort;
  4.    HANDLE hComm;
  5.    char portName[4];
  6.    DCB dcb;
  7.    char bufferIn[1024];
  8.    char bufferOut[1024];
  9. public:
  10. WinSerial(int numPort) {
  11.  NumPort=numPort;
  12.  wsprintf(portName,"COM%d",numPort);
  13.       //synchrone
  14.  hComm=CreateFile( portName,
  15.        GENERIC_READ | GENERIC_WRITE,
  16.        0,
  17.        0,
  18.        OPEN_EXISTING,
  19.        FILE_FLAG_OVERLAPPED,
  20.        0);
  21.  if (hComm==INVALID_HANDLE_VALUE) {
  22.   //printf("Handle NOTOK\n" );
  23.   exit(1);
  24.  }
  25.  FillMemory(&dcb,sizeof(dcb),0);
  26.  dcb.DCBlength=sizeof(dcb);
  27.       BuildCommDCB("9600,e,7,1",&dcb);
  28.  SetCommMask(hComm,EV_RXCHAR ||EV_RXFLAG); //alerte si caractere arrivé dans l'input
  29.  SetupComm(hComm,4096,1024);               //1024=taille max du bufferOut
  30.  SetCommState(hComm,&dcb);
  31. }
  32.    bool Ecrire(char *buffer) {
  33.       unsigned long nbreRetour;
  34.       if (WriteFile(hComm, buffer, strlen(buffer), &nbreRetour, NULL)) return true;
  35.       else return false;
  36.    }
  37.    bool EcrireChar(char c) {
  38.       unsigned long nbreRetour;
  39.       if (WriteFile(hComm, &c, 1, &nbreRetour, NULL)) return true;
  40.       else return false;
  41.    }
  42.    char LireChar() {
  43.       char c;
  44.       bool retour;
  45.       DWORD NbreLu;
  46.       retour=ReadFile(hComm,&c,1,(LPDWORD)&NbreLu,NULL);
  47.       return c;
  48.    }
  49. }

Reply

Marsh Posté le 13-04-2004 à 12:51:04    

la fonction qui ouvre le port COM :

Code :
  1. bool openCOMport(HANDLE& hPort, char* name, long baudRate, BYTE byteSize, char parity, int stopBits)
  2. {
  3.     bool bResult;   //boolean which indicates if the port has opened successfully
  4.     hPort = CreateFile (name,
  5.                         GENERIC_READ | GENERIC_WRITE,
  6.                         0,
  7.                         0,
  8.                         OPEN_EXISTING,
  9.                         FILE_ATTRIBUTE_NORMAL,
  10.                         0);
  11.     if (hPort == INVALID_HANDLE_VALUE)   //opening failed
  12.     {
  13.         bResult = false;
  14.         ShowMessage("pb ouverture port COM" );
  15.     }
  16.     else //COM port opened
  17.     {
  18.         //clearing of the buffer
  19.         PurgeComm(hPort,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
  20.         g_DCB.DCBlength = sizeof(DCB);  //initialization of COM port
  21.         GetCommState(hPort, &g_DCB);    //current configuration
  22.         //DCB modification
  23.         g_DCB.BaudRate = baudRate;
  24.         g_DCB.ByteSize = byteSize;
  25.         g_DCB.Parity = parity;
  26.         g_DCB.fParity = true;
  27.         g_DCB.StopBits = stopBits;
  28.         SetCommState(hPort, &g_DCB);     //configuration of serial link
  29.         timeouts.ReadIntervalTimeout = MAXDWORD;
  30.         timeouts.ReadTotalTimeoutMultiplier = 0;
  31.         timeouts.ReadTotalTimeoutConstant = 0;
  32.         timeouts.WriteTotalTimeoutMultiplier =5;
  33.         timeouts.WriteTotalTimeoutConstant = 5;
  34.         SetCommTimeouts(hPort, &timeouts);
  35.         bResult = true;
  36.     }
  37.     return bResult;
  38. }


 
 
L'envoi des donnees

Code :
  1. bool sendData(HANDLE hPort, const BYTE* buffer, int nCount)
  2. {
  3.     bool bResult;
  4.     unsigned long numBytes = 0;
  5.     if (hPort == NULL)  //COM port hasn't been opened
  6.         bResult = false;
  7.     else
  8.     {
  9.         WriteFile(hPort, buffer, nCount, &numBytes, NULL);
  10.         bResult = true;
  11.     }
  12.     return bResult;
  13. }


 
La creation du buffer :
en fait, j'ai une structure qui contient un tableau de 22 entiers 16bits
je les decoupe en 2 entiers 8bits chacun que je stock dans le buffer

Code :
  1. BYTE* createBuffer(TFuK_Msg* frame)
  2. {
  3.     BYTE* buffer = new BYTE[40];
  4.     BYTE* pTmp;
  5.     for (int i=0; i<20; i++)
  6.     {
  7.         pTmp = (BYTE*)&frame->DW[i]; //DW c'est le nom du tableau d'entiers
  8.         *(buffer+(2*i)) = *pTmp;
  9.         *(buffer+((2*i)+1)) = *(pTmp+1);
  10.     }
  11.     return buffer; //ici j'ai teste, le buffer vaut bien ce que je veuxqu'il vale...
  12. }


 
 
voila, je sais pas si c'est exactement ca que tu voulais... :p


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 13-04-2004 à 15:13:14    

Et comment appeles-tu la fonction openComPort ?

Reply

Marsh Posté le 13-04-2004 à 15:20:01    

Code :
  1. //les constantes globales
  2. const int CONNECTION_SPEED = 19200;
  3. const int BYTE_SIZE = 8;
  4. const char PARITY = NOPARITY;
  5. const int STOP_BITS = 1;
  6. //l'appel de openCOMport
  7. if (!openCOMport(hPort1, "COM1", CONNECTION_SPEED, BYTE_SIZE, PARITY, STOP_BITS))
  8.     //cas d'erreur
  9. else
  10.     //cas ou ca s'est ben ouvert


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 13-04-2004 à 16:40:08    

ca maaaaarche YOUPIIII !!!  :sol:


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 13-04-2004 à 18:20:26    

Et c'était quoi le pb ?

Reply

Marsh Posté le 13-04-2004 à 18:27:17    

j'ai bidouillé un peu partout : des signed char* (ou unsigned je sais plus) partout pour mes buffers d'ecriture et de lecture, des valeurs dans la DCB, et puis j'ai utilisé des constantes predefinies (NOPARITY, ONESTOPBIT)...  
mais en fait je suis pas sûr parce qu'avec tous les changements que j'ai fait et refait ben moi-meme je suis un peu perdu :/
je crois que j'ai ete plus rigoureux sur les initialisations et toute la programmation au niveau du port, à part ca je sais pas trop...
 
donc ouais, c'est pas une super demarche de programmeur, mais tant pis, l'important pour l'instant c'est que ca marche...  
si jamais ca replante ben... ca replantera pas !! :D

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed