système: windows 7
IDE: code::block
Bonjour,
Je sollicite encore une fois de l'aide sur ce site car j'ai rencontré un problème pour programmer un événement sur un port série sous windows.
Mon but est d'abord de créer un "time out" sur la fonction de lecture du port série ( ReadFile() ) pour qu'elle ne bloque pas indéfiniment le programme, ça j'ai pu le faire avec la fonction SetCommTimeout(). Ce "time out" une fois configuré, on peut invoquer la fonction ReadFile() qui se stoppe au bout du temps configuré précédemment, mais le problème c'est que si on reçoit des données à la moitié du "time out" il faut attendre la totalité du temps pour pouvoir traiter les données.
Donc, dans un deuxième temps, j'ai voulu instauré un événement avec un "time out" qui, lui, stoppe quand des données sont présentes sur le port série (ou plutôt dans les buffers internes du port série...enfin là je suis pas sur)
Ça aussi j'ai réussit à le réaliser, mais mon problème vient du fait que je n'arrive pas à récupérer les données après que l'événement se soit déclenché.
En fait mon programme réagit très bien, j'ai raccordé deux pc, sur l'un j'ai créer un générateur de trame qui envoi une chaîne de caractère passé en argument et sur l'autre il y a mon programme avec un événement qui attend des données en réception. Quant je déclenche le générateur de trame, mon événement détecte les données, puis il invoque la fonction ReadFile() qui au passage génère une erreur ( ERROR_IO_PENDING -> Overlapped I/O operation is in progress), puis j'affiche mon buffer de réception et là rien :p .
(ps: je vous rassure mes port COM sur chaque pc sont configurés exactement pareil)
Je pense que l'erreur générée y est pour quelque chose, et encore je ne croie pas (là aussi je ne suis pas sur).
Voici mon code :
Voilà, je pense qu'il y a quelque chose que je n'ai pas compris, peut-être que mon code n'est pas bon, la fonction ReadFile() n'est peut être pas à la bonne place.
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
89
90
91
92
93
94
95
96
97
98
99
100
101 #include <stdio.h> #include <stdlib.h> #include <windows.h> #define READ_TIMEOUT 9000 int main() { HANDLE fd = NULL; // descripteur de fichier du port com struct _DCB info; // struture de configuration du port com unsigned char buffer_r[101]; // buffer de donnees de reception DWORD bit_rw; // variable du nombre d'octet ecrit sur le port com char port[]="COM4\0"; // identifiant du port com sur le système // ouverture du port com fd = CreateFile( port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if(fd == INVALID_HANDLE_VALUE) { printf("\n :: Erreur d'ouverture du port %s ::\n", port); exit(0); } else printf("\n :: Ouverture du port %s ::\n", port); // recuperation de la configue du port com memset(&info, '\0', sizeof(struct _DCB)); // recupere la configue du port com if ( GetCommState(fd, &info) == 0) { printf(" :: Impossible de recuperer la configuration du port %s ::\n", port); exit(0); } else printf(" :: Configuration actuelle du port %s ::\n", port); // configuration du port com pour une utilisation classique 8N1 (8 data bits, N no parity, 1 stop bit) info.ByteSize = 8; info.BaudRate = CBR_9600; info.Parity = NOPARITY; info.StopBits = ONESTOPBIT; info.fBinary = 1; info.fParity = 0; info.fNull = 0; info.fOutxCtsFlow = 1; info.fOutxCtsFlow = 1; info.fDtrControl = DTR_CONTROL_ENABLE; info.fRtsControl = RTS_CONTROL_ENABLE; // configure le port com if( SetCommState(fd, &info) == 0) { printf("\n :: Impossible de configurer le port %s ::\n", port); exit(0); } else printf("\n :: Changement de la configuration du port %s ::\n", port); // création de l'événement OVERLAPPED com_ev = {0}; DWORD mask; DWORD iHandle; com_ev.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); // crée l'événement SetEvent( com_ev.hEvent ); // enregistre l'événement SetCommMask( fd, EV_RXCHAR ); // spécifie le type d'événement (ici EV_RXCHAR indique que l'on attend une donnée sur la broche RX de reception du port série) WaitCommEvent( fd, &mask, &com_ev ); // enregistre le type d'événement souhaité iHandle = WaitForSingleObject(com_ev.hEvent, READ_TIMEOUT); // attend que l'événement souhaité se produise, avec une valeur de time out de 9s if( iHandle == WAIT_OBJECT_0 ) // si l'événement c'est réalisé avec succée alors on récupére les données { if( ReadFile(fd, &buffer_r, (sizeof(buffer_r)-1), &bit_rw, &com_ev) == 0 ) // lit les données sur le port série { printf("ERROR: %ld\n\n", GetLastError() ); } printf(" buffer de reception: \n\n %s\n\n\n", buffer_r ); // affiche le buffer de reception des données }
J'ai aussi pensé que je devais mal configurer ma structure _DCB qui à son tour paramètre le port série (c'est probable).
J'ai testé tout un tas de chose dont voici les liens et rien ne marche ou du moins je suis pas doué. En tout cas j'ai trouvé aucun exemple propre qui fonctionne :
http://cpp.developpez.com/faq/vc/?page [...] ithSerialPort (je me suis inspiré de celui-ci)
http://msdn.microsoft.com/en-us/librar [...] serial_topic4
Merci d'avance pour toute réponse ou lien qui pourrait me mettre sur la voie.
Partager